Add --dump-bootstrap command to all un-inception implementations
This commit is contained in:
parent
fa40b3bc78
commit
ee15bc8a5f
9 changed files with 359 additions and 32 deletions
45
un.go
45
un.go
|
|
@ -342,7 +342,7 @@ func cmdSession(sessionList, sessionKill, sessionShell, network string, vcpu int
|
|||
fmt.Printf("%sSession created: %s%s\n", Green, result["id"], Reset)
|
||||
}
|
||||
|
||||
func cmdService(serviceName, servicePorts, serviceDomains, serviceType, serviceBootstrap, serviceList, serviceInfo, serviceLogs, serviceTail, serviceSleep, serviceWake, serviceDestroy, network string, vcpu int, apiKey string) {
|
||||
func cmdService(serviceName, servicePorts, serviceDomains, serviceType, serviceBootstrap, serviceList, serviceInfo, serviceLogs, serviceTail, serviceSleep, serviceWake, serviceDestroy, serviceExecute, serviceCommand, serviceDumpBootstrap, serviceDumpFile, network string, vcpu int, apiKey string) {
|
||||
if serviceList != "" {
|
||||
result := apiRequest("/services", "GET", nil, apiKey)
|
||||
services := result["services"].([]interface{})
|
||||
|
|
@ -412,6 +412,43 @@ func cmdService(serviceName, servicePorts, serviceDomains, serviceType, serviceB
|
|||
return
|
||||
}
|
||||
|
||||
if serviceExecute != "" {
|
||||
payload := map[string]interface{}{"command": serviceCommand}
|
||||
result := apiRequest("/services/"+serviceExecute+"/execute", "POST", payload, apiKey)
|
||||
if stdout, ok := result["stdout"].(string); ok {
|
||||
fmt.Printf("%s%s%s", Blue, stdout, Reset)
|
||||
}
|
||||
if stderr, ok := result["stderr"].(string); ok {
|
||||
fmt.Fprintf(os.Stderr, "%s%s%s", Red, stderr, Reset)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if serviceDumpBootstrap != "" {
|
||||
fmt.Fprintf(os.Stderr, "Fetching bootstrap script from %s...\n", serviceDumpBootstrap)
|
||||
payload := map[string]interface{}{"command": "cat /tmp/bootstrap.sh"}
|
||||
result := apiRequest("/services/"+serviceDumpBootstrap+"/execute", "POST", payload, apiKey)
|
||||
|
||||
if bootstrap, ok := result["stdout"].(string); ok && bootstrap != "" {
|
||||
if serviceDumpFile != "" {
|
||||
// Write to file
|
||||
err := os.WriteFile(serviceDumpFile, []byte(bootstrap), 0755)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%sError: Could not write to %s: %v%s\n", Red, serviceDumpFile, err, Reset)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("Bootstrap saved to %s\n", serviceDumpFile)
|
||||
} else {
|
||||
// Print to stdout
|
||||
fmt.Print(bootstrap)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%sError: Failed to fetch bootstrap (service not running or no bootstrap file)%s\n", Red, Reset)
|
||||
os.Exit(1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Create service
|
||||
if serviceName != "" {
|
||||
payload := map[string]interface{}{"name": serviceName}
|
||||
|
|
@ -645,6 +682,10 @@ func main() {
|
|||
serviceSleep := serviceCmd.String("sleep", "", "Freeze service")
|
||||
serviceWake := serviceCmd.String("wake", "", "Unfreeze service")
|
||||
serviceDestroy := serviceCmd.String("destroy", "", "Destroy service")
|
||||
serviceExecute := serviceCmd.String("execute", "", "Execute command in service")
|
||||
serviceCommand := serviceCmd.String("command", "", "Command to execute (with -execute)")
|
||||
serviceDumpBootstrap := serviceCmd.String("dump-bootstrap", "", "Dump bootstrap script")
|
||||
serviceDumpFile := serviceCmd.String("dump-file", "", "File to save bootstrap (with -dump-bootstrap)")
|
||||
serviceNetwork := serviceCmd.String("n", "", "Network mode")
|
||||
serviceVcpu := serviceCmd.Int("v", 0, "vCPU count")
|
||||
serviceKey := serviceCmd.String("k", "", "API key")
|
||||
|
|
@ -684,7 +725,7 @@ func main() {
|
|||
if vc == 0 {
|
||||
vc = *vcpu
|
||||
}
|
||||
cmdService(*serviceName, *servicePorts, *serviceDomains, *serviceType, *serviceBootstrap, *serviceList, *serviceInfo, *serviceLogs, *serviceTail, *serviceSleep, *serviceWake, *serviceDestroy, net, vc, key)
|
||||
cmdService(*serviceName, *servicePorts, *serviceDomains, *serviceType, *serviceBootstrap, *serviceList, *serviceInfo, *serviceLogs, *serviceTail, *serviceSleep, *serviceWake, *serviceDestroy, *serviceExecute, *serviceCommand, *serviceDumpBootstrap, *serviceDumpFile, net, vc, key)
|
||||
return
|
||||
|
||||
case "key":
|
||||
|
|
|
|||
46
un.js
46
un.js
|
|
@ -438,6 +438,34 @@ async function cmdService(args) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (args.dumpBootstrap) {
|
||||
console.error(`Fetching bootstrap script from ${args.dumpBootstrap}...`);
|
||||
const payload = { command: "cat /tmp/bootstrap.sh" };
|
||||
const result = await apiRequest(`/services/${args.dumpBootstrap}/execute`, "POST", payload, apiKey);
|
||||
|
||||
if (result.stdout) {
|
||||
const bootstrap = result.stdout;
|
||||
if (args.dumpFile) {
|
||||
// Write to file
|
||||
try {
|
||||
fs.writeFileSync(args.dumpFile, bootstrap);
|
||||
fs.chmodSync(args.dumpFile, 0o755);
|
||||
console.log(`Bootstrap saved to ${args.dumpFile}`);
|
||||
} catch (e) {
|
||||
console.error(`${RED}Error: Could not write to ${args.dumpFile}: ${e.message}${RESET}`);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
// Print to stdout
|
||||
process.stdout.write(bootstrap);
|
||||
}
|
||||
} else {
|
||||
console.error(`${RED}Error: Failed to fetch bootstrap (service not running or no bootstrap file)${RESET}`);
|
||||
process.exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.name) {
|
||||
const payload = { name: args.name };
|
||||
if (args.ports) payload.ports = args.ports.split(',').map(p => parseInt(p.trim()));
|
||||
|
|
@ -494,6 +522,8 @@ function parseArgs(argv) {
|
|||
destroy: null,
|
||||
execute: null,
|
||||
command_arg: null,
|
||||
dumpBootstrap: null,
|
||||
dumpFile: null,
|
||||
extend: false,
|
||||
};
|
||||
|
||||
|
|
@ -570,10 +600,10 @@ function parseArgs(argv) {
|
|||
} else if (arg === '--tail' && i + 1 < argv.length) {
|
||||
args.tail = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--sleep' && i + 1 < argv.length) {
|
||||
} else if (arg === '--freeze' && i + 1 < argv.length) {
|
||||
args.sleep = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--wake' && i + 1 < argv.length) {
|
||||
} else if (arg === '--unfreeze' && i + 1 < argv.length) {
|
||||
args.wake = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--destroy' && i + 1 < argv.length) {
|
||||
|
|
@ -585,6 +615,12 @@ function parseArgs(argv) {
|
|||
} else if (arg === '--command' && i + 1 < argv.length) {
|
||||
args.command_arg = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--dump-bootstrap' && i + 1 < argv.length) {
|
||||
args.dumpBootstrap = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--dump-file' && i + 1 < argv.length) {
|
||||
args.dumpFile = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--extend') {
|
||||
args.extend = true;
|
||||
i++;
|
||||
|
|
@ -648,11 +684,13 @@ Service options:
|
|||
--info ID Get service details
|
||||
--logs ID Get all logs
|
||||
--tail ID Get last 9000 lines
|
||||
--sleep ID Freeze service
|
||||
--wake ID Unfreeze service
|
||||
--freeze ID Freeze service
|
||||
--unfreeze ID Unfreeze service
|
||||
--destroy ID Destroy service
|
||||
--execute ID Execute command in service
|
||||
--command CMD Command to execute (with --execute)
|
||||
--dump-bootstrap ID Dump bootstrap script
|
||||
--dump-file FILE File to save bootstrap (with --dump-bootstrap)
|
||||
|
||||
Key options:
|
||||
--extend Open browser to extend key expiration
|
||||
|
|
|
|||
47
un.lua
47
un.lua
|
|
@ -454,6 +454,35 @@ local function cmd_service(options)
|
|||
return
|
||||
end
|
||||
|
||||
if options.dump_bootstrap then
|
||||
io.stderr:write("Fetching bootstrap script from " .. options.dump_bootstrap .. "...\n")
|
||||
local payload = { command = "cat /tmp/bootstrap.sh" }
|
||||
local result = api_request("/services/" .. options.dump_bootstrap .. "/execute", "POST", payload, api_key)
|
||||
|
||||
if result.stdout then
|
||||
local bootstrap = result.stdout
|
||||
if options.dump_file then
|
||||
-- Write to file
|
||||
local file = io.open(options.dump_file, "w")
|
||||
if not file then
|
||||
io.stderr:write(RED .. "Error: Could not write to " .. options.dump_file .. RESET .. "\n")
|
||||
os.exit(1)
|
||||
end
|
||||
file:write(bootstrap)
|
||||
file:close()
|
||||
os.execute("chmod 755 " .. options.dump_file)
|
||||
print("Bootstrap saved to " .. options.dump_file)
|
||||
else
|
||||
-- Print to stdout
|
||||
io.write(bootstrap)
|
||||
end
|
||||
else
|
||||
io.stderr:write(RED .. "Error: Failed to fetch bootstrap (service not running or no bootstrap file)" .. RESET .. "\n")
|
||||
os.exit(1)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if options.name then
|
||||
local payload = { name = options.name }
|
||||
if options.ports then
|
||||
|
|
@ -527,6 +556,8 @@ local function main()
|
|||
destroy = nil,
|
||||
execute = nil,
|
||||
command = nil,
|
||||
dump_bootstrap = nil,
|
||||
dump_file = nil,
|
||||
extend = false
|
||||
}
|
||||
|
||||
|
|
@ -597,10 +628,10 @@ local function main()
|
|||
elseif a == "--tail" then
|
||||
i = i + 1
|
||||
options.tail = arg[i]
|
||||
elseif a == "--sleep" then
|
||||
elseif a == "--freeze" then
|
||||
i = i + 1
|
||||
options.sleep = arg[i]
|
||||
elseif a == "--wake" then
|
||||
elseif a == "--unfreeze" then
|
||||
i = i + 1
|
||||
options.wake = arg[i]
|
||||
elseif a == "--destroy" then
|
||||
|
|
@ -612,6 +643,12 @@ local function main()
|
|||
elseif a == "--command" then
|
||||
i = i + 1
|
||||
options.command = arg[i]
|
||||
elseif a == "--dump-bootstrap" then
|
||||
i = i + 1
|
||||
options.dump_bootstrap = arg[i]
|
||||
elseif a == "--dump-file" then
|
||||
i = i + 1
|
||||
options.dump_file = arg[i]
|
||||
elseif a == "--extend" then
|
||||
options.extend = true
|
||||
elseif not a:match("^%-") then
|
||||
|
|
@ -667,11 +704,13 @@ Service options:
|
|||
--info ID Get service details
|
||||
--logs ID Get all logs
|
||||
--tail ID Get last 9000 lines
|
||||
--sleep ID Freeze service
|
||||
--wake ID Unfreeze service
|
||||
--freeze ID Freeze service
|
||||
--unfreeze ID Unfreeze service
|
||||
--destroy ID Destroy service
|
||||
--execute ID Execute command in service
|
||||
--command CMD Command to execute (with --execute)
|
||||
--dump-bootstrap ID Dump bootstrap script
|
||||
--dump-file FILE File to save bootstrap (with --dump-bootstrap)
|
||||
|
||||
Key options:
|
||||
--extend Open browser to extend/renew key
|
||||
|
|
|
|||
45
un.php
45
un.php
|
|
@ -436,6 +436,32 @@ function cmd_service($options) {
|
|||
return;
|
||||
}
|
||||
|
||||
if ($options['dump_bootstrap']) {
|
||||
fwrite(STDERR, "Fetching bootstrap script from {$options['dump_bootstrap']}...\n");
|
||||
$payload = ['command' => 'cat /tmp/bootstrap.sh'];
|
||||
$result = api_request("/services/{$options['dump_bootstrap']}/execute", 'POST', $payload, $api_key);
|
||||
|
||||
if (!empty($result['stdout'])) {
|
||||
$bootstrap = $result['stdout'];
|
||||
if ($options['dump_file']) {
|
||||
// Write to file
|
||||
if (file_put_contents($options['dump_file'], $bootstrap) === false) {
|
||||
fwrite(STDERR, RED . "Error: Could not write to {$options['dump_file']}" . RESET . "\n");
|
||||
exit(1);
|
||||
}
|
||||
chmod($options['dump_file'], 0755);
|
||||
echo "Bootstrap saved to {$options['dump_file']}\n";
|
||||
} else {
|
||||
// Print to stdout
|
||||
echo $bootstrap;
|
||||
}
|
||||
} else {
|
||||
fwrite(STDERR, RED . "Error: Failed to fetch bootstrap (service not running or no bootstrap file)" . RESET . "\n");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($options['name']) {
|
||||
$payload = ['name' => $options['name']];
|
||||
if ($options['ports']) {
|
||||
|
|
@ -500,6 +526,9 @@ function main() {
|
|||
'wake' => null,
|
||||
'destroy' => null,
|
||||
'execute' => null,
|
||||
'command' => null,
|
||||
'dump_bootstrap' => null,
|
||||
'dump_file' => null,
|
||||
'extend' => false
|
||||
];
|
||||
|
||||
|
|
@ -580,10 +609,10 @@ function main() {
|
|||
case '--tail':
|
||||
$options['tail'] = $argv[++$i];
|
||||
break;
|
||||
case '--sleep':
|
||||
case '--freeze':
|
||||
$options['sleep'] = $argv[++$i];
|
||||
break;
|
||||
case '--wake':
|
||||
case '--unfreeze':
|
||||
$options['wake'] = $argv[++$i];
|
||||
break;
|
||||
case '--destroy':
|
||||
|
|
@ -595,6 +624,12 @@ function main() {
|
|||
case '--command':
|
||||
$options['command'] = $argv[++$i];
|
||||
break;
|
||||
case '--dump-bootstrap':
|
||||
$options['dump_bootstrap'] = $argv[++$i];
|
||||
break;
|
||||
case '--dump-file':
|
||||
$options['dump_file'] = $argv[++$i];
|
||||
break;
|
||||
case '--extend':
|
||||
$options['extend'] = true;
|
||||
break;
|
||||
|
|
@ -651,11 +686,13 @@ Service options:
|
|||
--info ID Get service details
|
||||
--logs ID Get all logs
|
||||
--tail ID Get last 9000 lines
|
||||
--sleep ID Freeze service
|
||||
--wake ID Unfreeze service
|
||||
--freeze ID Freeze service
|
||||
--unfreeze ID Unfreeze service
|
||||
--destroy ID Destroy service
|
||||
--execute ID Execute command in service
|
||||
--command CMD Command to execute (with --execute)
|
||||
--dump-bootstrap ID Dump bootstrap script
|
||||
--dump-file FILE File to save bootstrap (with --dump-bootstrap)
|
||||
|
||||
Key options:
|
||||
-k KEY API key (or use UNSANDBOX_API_KEY env var)
|
||||
|
|
|
|||
44
un.pl
44
un.pl
|
|
@ -325,6 +325,34 @@ sub cmd_service {
|
|||
return;
|
||||
}
|
||||
|
||||
if ($options->{dump_bootstrap}) {
|
||||
print STDERR "Fetching bootstrap script from $options->{dump_bootstrap}...\n";
|
||||
my $payload = { command => 'cat /tmp/bootstrap.sh' };
|
||||
my $result = api_request("/services/$options->{dump_bootstrap}/execute", 'POST', $payload, $api_key);
|
||||
|
||||
if ($result->{stdout}) {
|
||||
my $bootstrap = $result->{stdout};
|
||||
if ($options->{dump_file}) {
|
||||
# Write to file
|
||||
open my $fh, '>', $options->{dump_file} or do {
|
||||
print STDERR "${RED}Error: Could not write to $options->{dump_file}: $!${RESET}\n";
|
||||
exit 1;
|
||||
};
|
||||
print $fh $bootstrap;
|
||||
close $fh;
|
||||
chmod 0755, $options->{dump_file};
|
||||
print "Bootstrap saved to $options->{dump_file}\n";
|
||||
} else {
|
||||
# Print to stdout
|
||||
print $bootstrap;
|
||||
}
|
||||
} else {
|
||||
print STDERR "${RED}Error: Failed to fetch bootstrap (service not running or no bootstrap file)${RESET}\n";
|
||||
exit 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($options->{name}) {
|
||||
my $payload = { name => $options->{name} };
|
||||
if ($options->{ports}) {
|
||||
|
|
@ -462,6 +490,8 @@ sub main {
|
|||
destroy => undef,
|
||||
execute => undef,
|
||||
command => undef,
|
||||
dump_bootstrap => undef,
|
||||
dump_file => undef,
|
||||
extend => 0
|
||||
);
|
||||
|
||||
|
|
@ -514,9 +544,9 @@ sub main {
|
|||
$options{logs} = $ARGV[++$i];
|
||||
} elsif ($arg eq '--tail') {
|
||||
$options{tail} = $ARGV[++$i];
|
||||
} elsif ($arg eq '--sleep') {
|
||||
} elsif ($arg eq '--freeze') {
|
||||
$options{sleep} = $ARGV[++$i];
|
||||
} elsif ($arg eq '--wake') {
|
||||
} elsif ($arg eq '--unfreeze') {
|
||||
$options{wake} = $ARGV[++$i];
|
||||
} elsif ($arg eq '--destroy') {
|
||||
$options{destroy} = $ARGV[++$i];
|
||||
|
|
@ -524,6 +554,10 @@ sub main {
|
|||
$options{execute} = $ARGV[++$i];
|
||||
} elsif ($arg eq '--command') {
|
||||
$options{command} = $ARGV[++$i];
|
||||
} elsif ($arg eq '--dump-bootstrap') {
|
||||
$options{dump_bootstrap} = $ARGV[++$i];
|
||||
} elsif ($arg eq '--dump-file') {
|
||||
$options{dump_file} = $ARGV[++$i];
|
||||
} elsif ($arg eq '--extend') {
|
||||
$options{extend} = 1;
|
||||
} elsif ($arg !~ /^-/) {
|
||||
|
|
@ -577,11 +611,13 @@ Service options:
|
|||
--info ID Get service details
|
||||
--logs ID Get all logs
|
||||
--tail ID Get last 9000 lines
|
||||
--sleep ID Freeze service
|
||||
--wake ID Unfreeze service
|
||||
--freeze ID Freeze service
|
||||
--unfreeze ID Unfreeze service
|
||||
--destroy ID Destroy service
|
||||
--execute ID Execute command in service
|
||||
--command CMD Command to execute (with --execute)
|
||||
--dump-bootstrap ID Dump bootstrap script
|
||||
--dump-file FILE File to save bootstrap (with --dump-bootstrap)
|
||||
|
||||
Key options:
|
||||
--extend Open browser to extend/renew key
|
||||
|
|
|
|||
31
un.py
31
un.py
|
|
@ -392,6 +392,31 @@ def cmd_service(args):
|
|||
print(f"{RED}{result['stderr']}{RESET}", end='', file=sys.stderr)
|
||||
return
|
||||
|
||||
if args.dump_bootstrap:
|
||||
print(f"Fetching bootstrap script from {args.dump_bootstrap}...", file=sys.stderr)
|
||||
payload = {"command": "cat /tmp/bootstrap.sh"}
|
||||
result = api_request(f"/services/{args.dump_bootstrap}/execute", method="POST", data=payload, api_key=api_key)
|
||||
|
||||
if result.get("stdout"):
|
||||
bootstrap = result["stdout"]
|
||||
if args.dump_file:
|
||||
# Write to file
|
||||
try:
|
||||
with open(args.dump_file, 'w') as f:
|
||||
f.write(bootstrap)
|
||||
os.chmod(args.dump_file, 0o755)
|
||||
print(f"Bootstrap saved to {args.dump_file}")
|
||||
except IOError as e:
|
||||
print(f"{RED}Error: Could not write to {args.dump_file}: {e}{RESET}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
else:
|
||||
# Print to stdout
|
||||
print(bootstrap, end='')
|
||||
else:
|
||||
print(f"{RED}Error: Failed to fetch bootstrap (service not running or no bootstrap file){RESET}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
return
|
||||
|
||||
# Create new service
|
||||
if args.name:
|
||||
payload = {"name": args.name}
|
||||
|
|
@ -478,11 +503,13 @@ Examples:
|
|||
service_parser.add_argument("--info", metavar="ID", help="Get service details")
|
||||
service_parser.add_argument("--tail", metavar="ID", help="Get last 9000 lines of logs")
|
||||
service_parser.add_argument("--logs", metavar="ID", help="Get all logs")
|
||||
service_parser.add_argument("--sleep", metavar="ID", help="Freeze service")
|
||||
service_parser.add_argument("--wake", metavar="ID", help="Unfreeze service")
|
||||
service_parser.add_argument("--freeze", metavar="ID", help="Freeze service")
|
||||
service_parser.add_argument("--unfreeze", metavar="ID", help="Unfreeze service")
|
||||
service_parser.add_argument("--destroy", metavar="ID", help="Destroy service")
|
||||
service_parser.add_argument("--execute", metavar="ID", help="Execute command in service")
|
||||
service_parser.add_argument("--command", help="Command to execute (with --execute)")
|
||||
service_parser.add_argument("--dump-bootstrap", metavar="ID", help="Dump bootstrap script")
|
||||
service_parser.add_argument("--dump-file", metavar="FILE", help="File to save bootstrap (with --dump-bootstrap)")
|
||||
service_parser.add_argument("-n", "--network", choices=["zerotrust", "semitrusted"])
|
||||
service_parser.add_argument("-v", "--vcpu", type=int, choices=range(1, 9))
|
||||
service_parser.add_argument("-k", "--api-key")
|
||||
|
|
|
|||
46
un.rb
46
un.rb
|
|
@ -391,6 +391,34 @@ def cmd_service(options)
|
|||
return
|
||||
end
|
||||
|
||||
if options[:dump_bootstrap]
|
||||
warn "Fetching bootstrap script from #{options[:dump_bootstrap]}..."
|
||||
payload = { command: 'cat /tmp/bootstrap.sh' }
|
||||
result = api_request("/services/#{options[:dump_bootstrap]}/execute", method: 'POST', data: payload, api_key: api_key)
|
||||
|
||||
if result['stdout']
|
||||
bootstrap = result['stdout']
|
||||
if options[:dump_file]
|
||||
# Write to file
|
||||
begin
|
||||
File.write(options[:dump_file], bootstrap)
|
||||
File.chmod(0755, options[:dump_file])
|
||||
puts "Bootstrap saved to #{options[:dump_file]}"
|
||||
rescue => e
|
||||
warn "#{RED}Error: Could not write to #{options[:dump_file]}: #{e.message}#{RESET}"
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
# Print to stdout
|
||||
print bootstrap
|
||||
end
|
||||
else
|
||||
warn "#{RED}Error: Failed to fetch bootstrap (service not running or no bootstrap file)#{RESET}"
|
||||
exit 1
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if options[:name]
|
||||
payload = { name: options[:name] }
|
||||
payload[:ports] = options[:ports].split(',').map(&:to_i) if options[:ports]
|
||||
|
|
@ -447,6 +475,8 @@ def main
|
|||
wake: nil,
|
||||
destroy: nil,
|
||||
execute: nil,
|
||||
dump_bootstrap: nil,
|
||||
dump_file: nil,
|
||||
extend: false
|
||||
}
|
||||
|
||||
|
|
@ -519,10 +549,10 @@ def main
|
|||
when '--tail'
|
||||
i += 1
|
||||
options[:tail] = ARGV[i]
|
||||
when '--sleep'
|
||||
when '--freeze'
|
||||
i += 1
|
||||
options[:sleep] = ARGV[i]
|
||||
when '--wake'
|
||||
when '--unfreeze'
|
||||
i += 1
|
||||
options[:wake] = ARGV[i]
|
||||
when '--destroy'
|
||||
|
|
@ -534,6 +564,12 @@ def main
|
|||
when '--command'
|
||||
i += 1
|
||||
options[:command] = ARGV[i]
|
||||
when '--dump-bootstrap'
|
||||
i += 1
|
||||
options[:dump_bootstrap] = ARGV[i]
|
||||
when '--dump-file'
|
||||
i += 1
|
||||
options[:dump_file] = ARGV[i]
|
||||
when '--extend'
|
||||
options[:extend] = true
|
||||
else
|
||||
|
|
@ -591,11 +627,13 @@ def main
|
|||
--info ID Get service details
|
||||
--logs ID Get all logs
|
||||
--tail ID Get last 9000 lines
|
||||
--sleep ID Freeze service
|
||||
--wake ID Unfreeze service
|
||||
--freeze ID Freeze service
|
||||
--unfreeze ID Unfreeze service
|
||||
--destroy ID Destroy service
|
||||
--execute ID Execute command in service
|
||||
--command CMD Command to execute (with --execute)
|
||||
--dump-bootstrap ID Dump bootstrap script
|
||||
--dump-file FILE File to save bootstrap (with --dump-bootstrap)
|
||||
|
||||
Key options:
|
||||
-k KEY API key (or use UNSANDBOX_API_KEY env var)
|
||||
|
|
|
|||
41
un.sh
41
un.sh
|
|
@ -449,11 +449,11 @@ cmd_service() {
|
|||
tail="$2"
|
||||
shift 2
|
||||
;;
|
||||
--sleep)
|
||||
--freeze)
|
||||
sleep="$2"
|
||||
shift 2
|
||||
;;
|
||||
--wake)
|
||||
--unfreeze)
|
||||
wake="$2"
|
||||
shift 2
|
||||
;;
|
||||
|
|
@ -469,6 +469,14 @@ cmd_service() {
|
|||
command="$2"
|
||||
shift 2
|
||||
;;
|
||||
--dump-bootstrap)
|
||||
dump_bootstrap="$2"
|
||||
shift 2
|
||||
;;
|
||||
--dump-file)
|
||||
dump_file="$2"
|
||||
shift 2
|
||||
;;
|
||||
-n)
|
||||
network="$2"
|
||||
shift 2
|
||||
|
|
@ -548,6 +556,29 @@ cmd_service() {
|
|||
return
|
||||
fi
|
||||
|
||||
if [[ -n "$dump_bootstrap" ]]; then
|
||||
echo "Fetching bootstrap script from $dump_bootstrap..." >&2
|
||||
local payload=$(jq -n '{command: "cat /tmp/bootstrap.sh"}')
|
||||
local result=$(api_request "/services/$dump_bootstrap/execute" "POST" "$payload" "$api_key")
|
||||
local bootstrap=$(echo "$result" | jq -r '.stdout // empty')
|
||||
|
||||
if [[ -n "$bootstrap" ]]; then
|
||||
if [[ -n "$dump_file" ]]; then
|
||||
# Write to file
|
||||
echo "$bootstrap" > "$dump_file"
|
||||
chmod 755 "$dump_file"
|
||||
echo "Bootstrap saved to $dump_file"
|
||||
else
|
||||
# Print to stdout
|
||||
echo -n "$bootstrap"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}Error: Failed to fetch bootstrap (service not running or no bootstrap file)${RESET}" >&2
|
||||
exit 1
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "$name" ]]; then
|
||||
local payload=$(jq -n --arg n "$name" '{name: $n}')
|
||||
|
||||
|
|
@ -774,11 +805,13 @@ Service options:
|
|||
--info ID Get service details
|
||||
--logs ID Get all logs
|
||||
--tail ID Get last 9000 lines
|
||||
--sleep ID Freeze service
|
||||
--wake ID Unfreeze service
|
||||
--freeze ID Freeze service
|
||||
--unfreeze ID Unfreeze service
|
||||
--destroy ID Destroy service
|
||||
--execute ID Execute command in service
|
||||
--command CMD Command to execute (with --execute)
|
||||
--dump-bootstrap ID Dump bootstrap script
|
||||
--dump-file FILE File to save bootstrap (with --dump-bootstrap)
|
||||
|
||||
Key options:
|
||||
-k KEY API key to validate
|
||||
|
|
|
|||
46
un.ts
46
un.ts
|
|
@ -393,6 +393,34 @@ async function cmdService(args: Args): Promise<void> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (args.dumpBootstrap) {
|
||||
console.error(`Fetching bootstrap script from ${args.dumpBootstrap}...`);
|
||||
const payload = { command: "cat /tmp/bootstrap.sh" };
|
||||
const result = await apiRequest(`/services/${args.dumpBootstrap}/execute`, "POST", payload, apiKey);
|
||||
|
||||
if (result.stdout) {
|
||||
const bootstrap = result.stdout;
|
||||
if (args.dumpFile) {
|
||||
// Write to file
|
||||
try {
|
||||
fs.writeFileSync(args.dumpFile, bootstrap);
|
||||
fs.chmodSync(args.dumpFile, 0o755);
|
||||
console.log(`Bootstrap saved to ${args.dumpFile}`);
|
||||
} catch (e: any) {
|
||||
console.error(`${RED}Error: Could not write to ${args.dumpFile}: ${e.message}${RESET}`);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
// Print to stdout
|
||||
process.stdout.write(bootstrap);
|
||||
}
|
||||
} else {
|
||||
console.error(`${RED}Error: Failed to fetch bootstrap (service not running or no bootstrap file)${RESET}`);
|
||||
process.exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.name) {
|
||||
const payload: any = { name: args.name };
|
||||
if (args.ports) payload.ports = args.ports.split(',').map(p => parseInt(p.trim()));
|
||||
|
|
@ -520,6 +548,8 @@ function parseArgs(argv: string[]): Args {
|
|||
destroy: null,
|
||||
execute: null,
|
||||
command_arg: null,
|
||||
dumpBootstrap: null,
|
||||
dumpFile: null,
|
||||
extend: false,
|
||||
};
|
||||
|
||||
|
|
@ -596,10 +626,10 @@ function parseArgs(argv: string[]): Args {
|
|||
} else if (arg === '--tail' && i + 1 < argv.length) {
|
||||
args.tail = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--sleep' && i + 1 < argv.length) {
|
||||
} else if (arg === '--freeze' && i + 1 < argv.length) {
|
||||
args.sleep = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--wake' && i + 1 < argv.length) {
|
||||
} else if (arg === '--unfreeze' && i + 1 < argv.length) {
|
||||
args.wake = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--destroy' && i + 1 < argv.length) {
|
||||
|
|
@ -611,6 +641,12 @@ function parseArgs(argv: string[]): Args {
|
|||
} else if (arg === '--command' && i + 1 < argv.length) {
|
||||
args.command_arg = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--dump-bootstrap' && i + 1 < argv.length) {
|
||||
args.dumpBootstrap = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--dump-file' && i + 1 < argv.length) {
|
||||
args.dumpFile = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--extend') {
|
||||
args.extend = true;
|
||||
i++;
|
||||
|
|
@ -674,11 +710,13 @@ Service options:
|
|||
--info ID Get service details
|
||||
--logs ID Get all logs
|
||||
--tail ID Get last 9000 lines
|
||||
--sleep ID Freeze service
|
||||
--wake ID Unfreeze service
|
||||
--freeze ID Freeze service
|
||||
--unfreeze ID Unfreeze service
|
||||
--destroy ID Destroy service
|
||||
--execute ID Execute command in service
|
||||
--command CMD Command to execute (with --execute)
|
||||
--dump-bootstrap ID Dump bootstrap script
|
||||
--dump-file FILE File to save bootstrap (with --dump-bootstrap)
|
||||
|
||||
Key options:
|
||||
--extend Open browser to extend key expiration
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue