Module: LanguageOperator::CLI::Commands::System::Exec
- Included in:
- Base
- Defined in:
- lib/language_operator/cli/commands/system/exec.rb
Overview
Agent execution in test pod
Class Method Summary collapse
Class Method Details
.included(base) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/language_operator/cli/commands/system/exec.rb', line 9 def self.included(base) base.class_eval do desc 'exec [AGENT_FILE]', 'Execute an agent file in a test pod on the cluster' long_desc " Deploy and execute an agent file in a temporary test pod on the Kubernetes cluster.\n\n This command creates a ConfigMap with the agent code, deploys a test pod,\n streams the logs until completion, and cleans up all resources.\n\n The agent code is mounted at /etc/agent/code/agent.rb as expected by the agent runtime.\n\n Agent code can be provided either as a file path or via STDIN.\n If no file path is provided, the command will read from STDIN.\n\n Examples:\n # Execute a synthesized agent file\n langop system exec agent.rb\n\n # Execute with a custom agent name\n langop system exec agent.rb --agent-name my-test\n\n # Keep the pod after execution for debugging\n langop system exec agent.rb --keep-pod\n\n # Use a different agent image\n langop system exec agent.rb --image ghcr.io/language-operator/agent:v0.1.0\n\n # Read agent code from STDIN\n cat agent.rb | langop system exec\n\n # Pipe synthesized code directly to execution\n cat agent.txt | langop system synthesize | langop system exec\n DESC\n option :agent_name, type: :string, default: 'test-agent', desc: 'Name for the test agent pod'\n option :keep_pod, type: :boolean, default: false, desc: 'Keep the pod after execution (for debugging)'\n option :image, type: :string, default: 'ghcr.io/language-operator/agent:latest', desc: 'Agent container image'\n option :timeout, type: :numeric, default: 300, desc: 'Timeout in seconds for agent execution'\n def exec(agent_file = nil)\n handle_command_error('exec agent') do\n # Verify cluster is selected\n unless ctx.client\n Formatters::ProgressFormatter.error('No cluster context available')\n puts\n puts 'Please configure kubectl with a valid cluster context:'\n puts ' kubectl config get-contexts'\n puts ' kubectl config use-context <context-name>'\n exit 1\n end\n\n # Read agent code from file or STDIN\n agent_code = if agent_file && !agent_file.strip.empty?\n # Read from file\n unless File.exist?(agent_file)\n Formatters::ProgressFormatter.error(\"Agent file not found: \#{agent_file}\")\n exit 1\n end\n File.read(agent_file)\n elsif $stdin.tty?\n # Read from STDIN\n Formatters::ProgressFormatter.error('No agent code provided')\n puts\n puts 'Provide agent code either as a file or via STDIN:'\n puts ' langop system exec agent.rb'\n puts ' cat agent.rb | langop system exec'\n exit 1\n else\n code = $stdin.read.strip\n if code.empty?\n Formatters::ProgressFormatter.error('No agent code provided')\n puts\n puts 'Provide agent code either as a file or via STDIN:'\n puts ' langop system exec agent.rb'\n puts ' cat agent.rb | langop system exec'\n exit 1\n end\n code\n end\n\n # Generate unique names\n timestamp = Time.now.to_i\n configmap_name = \"\#{options[:agent_name]}-code-\#{timestamp}\"\n pod_name = \"\#{options[:agent_name]}-\#{timestamp}\"\n\n begin\n # Create ConfigMap with agent code\n Formatters::ProgressFormatter.with_spinner('Creating ConfigMap with agent code') do\n create_agent_configmap(configmap_name, agent_code)\n end\n\n # Create test pod\n Formatters::ProgressFormatter.with_spinner('Creating test pod') do\n create_test_pod(pod_name, configmap_name, options[:image])\n end\n\n # Wait for pod to be ready or running\n Formatters::ProgressFormatter.with_spinner('Waiting for pod to start') do\n wait_for_pod_start(pod_name, timeout: 60)\n end\n\n # Stream logs until pod completes\n stream_pod_logs(pod_name, timeout: options[:timeout])\n\n # Wait for pod to fully terminate and get final status\n exit_code = wait_for_pod_termination(pod_name)\n\n if exit_code&.zero?\n Formatters::ProgressFormatter.success('Agent completed successfully')\n elsif exit_code\n Formatters::ProgressFormatter.error(\"Agent failed with exit code: \#{exit_code}\")\n else\n Formatters::ProgressFormatter.warn('Unable to determine pod exit status')\n end\n ensure\n # Clean up resources unless --keep-pod\n puts\n puts\n if options[:keep_pod]\n Formatters::ProgressFormatter.info('Resources kept for debugging:')\n puts \" Pod: \#{pod_name}\"\n puts \" ConfigMap: \#{configmap_name}\"\n puts\n puts \"To view logs: kubectl logs -n \#{ctx.namespace} \#{pod_name}\"\n puts \"To delete: kubectl delete pod,configmap -n \#{ctx.namespace} \#{pod_name} \#{configmap_name}\"\n else\n Formatters::ProgressFormatter.with_spinner('Cleaning up resources') do\n delete_pod(pod_name)\n delete_configmap(configmap_name)\n end\n end\n end\n end\n end\n end\nend\n" |