From fcb5964f8d1b5d4b85316acd4e686754a6f9a08c Mon Sep 17 00:00:00 2001 From: Mahmoud-Emad Date: Fri, 14 Nov 2025 11:20:26 +0200 Subject: [PATCH] feat: Add `run` command for Heroscript execution - Add `cmd_run` to execute heroscripts from files or inline - Implement file path handling and inline script execution - Add Linux platform check for HeroPods initialization - Update documentation to reflect Linux-only requirement --- cli/hero.v | 3 +- examples/gittools/test_check.hero | 1 - lib/core/herocmds/run.v | 114 +++++++++++++++++++++++++++++ lib/virt/heropods/heropods_model.v | 6 ++ lib/virt/heropods/readme.md | 20 +++-- 5 files changed, 136 insertions(+), 8 deletions(-) delete mode 100644 examples/gittools/test_check.hero create mode 100644 lib/core/herocmds/run.v diff --git a/cli/hero.v b/cli/hero.v index a6abaf80..1068b712 100644 --- a/cli/hero.v +++ b/cli/hero.v @@ -86,6 +86,7 @@ fn do() ! { base.redis_install()! + // herocmds.cmd_run(mut cmd) herocmds.cmd_git(mut cmd) herocmds.cmd_generator(mut cmd) herocmds.cmd_docusaurus(mut cmd) @@ -104,4 +105,4 @@ fn main() { print_backtrace() exit(1) } -} \ No newline at end of file +} diff --git a/examples/gittools/test_check.hero b/examples/gittools/test_check.hero deleted file mode 100644 index 1c0bd6ab..00000000 --- a/examples/gittools/test_check.hero +++ /dev/null @@ -1 +0,0 @@ -!!git.check filter:'herolib' \ No newline at end of file diff --git a/lib/core/herocmds/run.v b/lib/core/herocmds/run.v new file mode 100644 index 00000000..e4c38131 --- /dev/null +++ b/lib/core/herocmds/run.v @@ -0,0 +1,114 @@ +module herocmds + +import incubaid.herolib.ui.console +import incubaid.herolib.core.playcmds +import os +import cli { Command, Flag } + +pub fn cmd_run(mut cmdroot Command) { + mut cmd_run := Command{ + name: 'run' + description: 'Run heroscript from inline string or file' + usage: ' +Run HeroScript + +USAGE: + hero run [flags] [file] + hero run -s "heroscript content" + +EXAMPLES: + # Run from file + hero run script.heroscript + hero run examples/virt/heropods/demo.heroscript + + # Run inline heroscript + hero run -s "!!heropods.configure name:\'demo\' reset:false use_podman:true" + + # Run multi-line heroscript + hero run -s " + !!heropods.configure + name:\'demo\' + reset:false + use_podman:true + + !!heropods.container_new + name:\'demo_container\' + image:\'alpine_3_20\' + " + ' + required_args: 0 + execute: cmd_run_execute + } + + cmd_run.add_flag(Flag{ + flag: .string + required: false + name: 'script' + abbrev: 's' + description: 'Inline heroscript to execute' + }) + + cmd_run.add_flag(Flag{ + flag: .bool + required: false + name: 'reset' + abbrev: 'r' + description: 'Reset before running' + }) + + cmdroot.add_command(cmd_run) +} + +fn cmd_run_execute(cmd Command) ! { + mut reset := cmd.flags.get_bool('reset') or { false } + mut inline_script := cmd.flags.get_string('script') or { '' } + + // If inline script is provided via -s flag + if inline_script != '' { + console.print_header('Running inline heroscript...') + + // Create a temporary file to hold the heroscript + temp_dir := os.temp_dir() + temp_file := '${temp_dir}/hero_inline_${os.getpid()}.heroscript' + + // Write the inline script to temp file + os.write_file(temp_file, inline_script) or { + return error('Failed to write temporary heroscript file: ${err}') + } + + // Ensure cleanup + defer { + os.rm(temp_file) or {} + } + + // Run the heroscript + playcmds.run(heroscript_path: temp_file, reset: reset)! + return + } + + // If file path is provided as argument + if cmd.args.len > 0 { + mut path := cmd.args[0] + + // Handle "." as current working directory + if path == '.' { + path = os.getwd() + } else { + // Expand home directory + path = path.replace('~', os.home_dir()) + + // Validate that path exists + if !os.exists(path) { + return error('File does not exist: ${path}') + } + } + + console.print_header('Running heroscript from file: ${path}') + playcmds.run(heroscript_path: path, reset: reset)! + return + } + + // No script provided + return error('No heroscript provided. Use -s for inline script or provide a file path.\n\n${cmd.help_message()}') +} + diff --git a/lib/virt/heropods/heropods_model.v b/lib/virt/heropods/heropods_model.v index c3aa5280..b898788b 100644 --- a/lib/virt/heropods/heropods_model.v +++ b/lib/virt/heropods/heropods_model.v @@ -4,6 +4,7 @@ import incubaid.herolib.data.encoderhero import incubaid.herolib.osal.core as osal import incubaid.herolib.virt.crun import incubaid.herolib.core.logger +import incubaid.herolib.core import os import sync @@ -74,6 +75,11 @@ fn obj_init(mycfg_ HeroPods) !HeroPods { // initialize performs heavy initialization operations // This should be called after obj_init in the factory pattern fn (mut self HeroPods) initialize() ! { + // Check platform - HeroPods requires Linux + if core.is_osx()! { + return error('HeroPods requires Linux. It uses Linux-specific tools (ip, iptables, nsenter, crun) that are not available on macOS. Please run HeroPods on a Linux system or use Docker/Podman directly on macOS.') + } + // Create base directories osal.exec( cmd: 'mkdir -p ${self.base_dir}/images ${self.base_dir}/configs ${self.base_dir}/runtime' diff --git a/lib/virt/heropods/readme.md b/lib/virt/heropods/readme.md index 119dfb68..ab57b839 100644 --- a/lib/virt/heropods/readme.md +++ b/lib/virt/heropods/readme.md @@ -2,6 +2,20 @@ HeroPods is a lightweight container management system built on crun (OCI runtime), providing Docker-like functionality with bridge networking, automatic IP allocation, and image management via Podman. +## Requirements + +**Platform:** Linux only + +HeroPods requires Linux-specific tools and will not work on macOS or Windows: + +- `crun` (OCI runtime) +- `ip` (iproute2 package) +- `iptables` (for NAT) +- `nsenter` (for network namespace management) +- `podman` (optional, for image management) + +On macOS/Windows, please use Docker or Podman directly instead of HeroPods. + ## Quick Start ### Basic Usage @@ -106,9 +120,3 @@ See `examples/virt/heropods/` for more detailed examples: - `heropods.vsh` - Complete API demonstration - `demo.heroscript` - HeroScript usage - `runcommands.vsh` - Simple command execution - -## Requirements - -- **crun**: OCI container runtime (auto-installed if missing) -- **podman** (optional): For pulling Docker images -- **Linux**: Bridge networking requires Linux kernel features