#!/usr/bin/env python """ Script to deploy the Nomad MCP service using our own Nomad client. """ import os import sys import json import subprocess from dotenv import load_dotenv from app.services.nomad_client import NomadService # Load environment variables from .env file load_dotenv() def check_git_status(): """Check if there are uncommitted changes in the git repository.""" try: # Check for uncommitted changes result = subprocess.run( ["git", "status", "--porcelain"], capture_output=True, text=True, check=True ) if result.stdout.strip(): print("\n⚠️ WARNING: You have uncommitted changes in your repository!") print("The Nomad job will pull code from Gitea, not your local changes.") print("Uncommitted files:") for line in result.stdout.strip().split('\n'): print(f" - {line}") # Check if we're behind the remote result = subprocess.run( ["git", "status", "-sb"], capture_output=True, text=True, check=True ) if "behind" in result.stdout: print("\n⚠️ Your local branch is behind the remote repository!") print("The deployed code will be from the remote repository, not your local version.") print("\nDo you want to:") print("1. Continue deployment anyway (will use the code in Gitea)") print("2. Abort to commit and push your changes first") choice = input("\nEnter your choice (1 or 2): ").strip() if choice == "2": print("\nDeployment aborted. Please commit and push your changes first:") print(" git add .") print(" git commit -m \"Your commit message\"") print(" git push") sys.exit(0) elif choice == "1": print("\nContinuing with deployment using the code in Gitea...") else: print("\nInvalid choice. Aborting deployment.") sys.exit(1) else: # Check if we're up to date with remote result = subprocess.run( ["git", "status", "-sb"], capture_output=True, text=True, check=True ) if "behind" in result.stdout: print("\n⚠️ Your local branch is behind the remote repository!") print("The deployed code will be from the remote repository, not your local version.") print("Do you want to pull the latest changes before checking? (y/n)") choice = input().strip().lower() if choice == "y": subprocess.run(["git", "pull"], check=True) print("Successfully pulled latest changes.") else: print("Continuing with deployment using the code in Gitea...") else: print("✅ Git repository is clean and up to date with remote.") except subprocess.CalledProcessError as e: print(f"\n⚠️ Warning: Failed to check git status: {e}") print("Unable to verify if all changes are committed and pushed.") print("Please ensure your code is committed and pushed to Gitea before deploying.") print("\nDo you want to continue anyway? (y/n)") choice = input().strip().lower() if choice != "y": print("Deployment aborted.") sys.exit(0) except Exception as e: print(f"\n⚠️ Warning: Error checking git status: {str(e)}") print("Unable to verify if all changes are committed and pushed.") print("Please ensure your code is committed and pushed to Gitea before deploying.") def main(): print("Deploying Nomad MCP service using our own Nomad client...") # Check git status before deployment check_git_status() # Check if NOMAD_ADDR is configured nomad_addr = os.getenv("NOMAD_ADDR") if not nomad_addr: print("Error: NOMAD_ADDR is not configured in .env file.") sys.exit(1) print(f"Connecting to Nomad at: {nomad_addr}") try: # Initialize the Nomad service nomad_service = NomadService() # Use the HCL file directly with the Nomad CLI print("Registering and starting the nomad-mcp job...") # Create a job specification directly job_spec = { "Job": { "ID": "nomad-mcp", "Name": "nomad-mcp", "Type": "service", "Datacenters": ["jm"], "Namespace": "development", "TaskGroups": [ { "Name": "app", "Count": 1, "Networks": [ { "DynamicPorts": [ { "Label": "http", "To": 8000 } ] } ], "Tasks": [ { "Name": "nomad-mcp", "Driver": "docker", "Config": { "image": "registry.dev.meisheng.group/nomad_mcp:20250226", "ports": ["http"], "command": "python", "args": ["-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"], "mount": [ { "type": "bind", "source": "local/nomad_mcp", "target": "/app", "readonly": False } ] }, "Artifacts": [ { "GetterSource": "git::ssh://git@gitea.service.mesh:2222/Mei_Sheng_Textiles/nomad_mcp.git", "RelativeDest": "local/nomad_mcp", "GetterOptions": { "ref": "main", "sshkey": "LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUFNd0FBQUF0emMyZ3RaVwpReU5UVXhPUUFBQUNBY01oYkNPVXhFOHBYQ3d5UEh0ZFR4aThHU0pzNEdTNXZ6ZTR6Tm1ueUYvUUFBQUtCQm5RZi9RWjBICi93QUFBQXR6YzJndFpXUXlOVFV4T1FBQUFDQWNNaGJDT1V4RThwWEN3eVBIdGRUeGk4R1NKczRHUzV2emU0ek5tbnlGL1EKQUFBRURreWwzQlZlek9YUWZUNzZac0NkYTZPNTFnMExsb25EMEd6L2Y4SHh3dzRCd3lGc0k1VEVUeWxjTERJOGUxMVBHTAp3WkltemdaTG0vTjdqTTJhZklYOUFBQUFHR1JsY0d4dmVTQnJaWGtnWm05eUlHNXZiV0ZrWDIxamNBRUNBd1FGCi0tLS0tRU5EIE9QRU5TU0ggUFJJVkFURSBLRVktLS0tLQo=" } } ], "Env": { "NOMAD_ADDR": "http://pjmldk01.ds.meisheng.group:4646", "NOMAD_NAMESPACE": "development", "NOMAD_SKIP_VERIFY": "true", "PORT": "8000", "HOST": "0.0.0.0", "LOG_LEVEL": "INFO", "RELOAD": "true", "PYTHONPATH": "/app", "STATIC_DIR": "/local/nomad_mcp/static" }, "Resources": { "CPU": 200, "MemoryMB": 256 }, "Services": [ { "Name": "nomad-mcp", "PortLabel": "http", "Tags": [ "traefik.enable=true", "traefik.http.routers.nomad-mcp.entryPoints=https", "traefik.http.routers.nomad-mcp.rule=Host(`nomad_mcp.dev.meisheng.group`)", "traefik.http.routers.nomad-mcp.middlewares=proxyheaders@consulcatalog" ], "Checks": [ { "Type": "http", "Path": "/api/health", "Interval": 10000000000, "Timeout": 2000000000, "CheckRestart": { "Limit": 3, "Grace": 60000000000 } } ] } ] } ] } ], "Update": { "MaxParallel": 1, "MinHealthyTime": 30000000000, "HealthyDeadline": 300000000000, "AutoRevert": True } } } # Start the job response = nomad_service.start_job(job_spec) print("\nJob registration response:") print(json.dumps(response, indent=2)) if response.get("status") == "started": print("\n✅ Nomad MCP service deployed successfully!") print(f"Job ID: {response.get('job_id')}") print(f"Evaluation ID: {response.get('eval_id')}") print("\nThe service will be available at: https://nomad_mcp.dev.meisheng.group") else: print("\n❌ Failed to deploy Nomad MCP service.") print(f"Status: {response.get('status')}") print(f"Message: {response.get('message', 'Unknown error')}") except Exception as e: print(f"Error deploying Nomad MCP service: {str(e)}") sys.exit(1) if __name__ == "__main__": main()