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)
|
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 != "" {
|
if serviceList != "" {
|
||||||
result := apiRequest("/services", "GET", nil, apiKey)
|
result := apiRequest("/services", "GET", nil, apiKey)
|
||||||
services := result["services"].([]interface{})
|
services := result["services"].([]interface{})
|
||||||
|
|
@ -412,6 +412,43 @@ func cmdService(serviceName, servicePorts, serviceDomains, serviceType, serviceB
|
||||||
return
|
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
|
// Create service
|
||||||
if serviceName != "" {
|
if serviceName != "" {
|
||||||
payload := map[string]interface{}{"name": serviceName}
|
payload := map[string]interface{}{"name": serviceName}
|
||||||
|
|
@ -645,6 +682,10 @@ func main() {
|
||||||
serviceSleep := serviceCmd.String("sleep", "", "Freeze service")
|
serviceSleep := serviceCmd.String("sleep", "", "Freeze service")
|
||||||
serviceWake := serviceCmd.String("wake", "", "Unfreeze service")
|
serviceWake := serviceCmd.String("wake", "", "Unfreeze service")
|
||||||
serviceDestroy := serviceCmd.String("destroy", "", "Destroy 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")
|
serviceNetwork := serviceCmd.String("n", "", "Network mode")
|
||||||
serviceVcpu := serviceCmd.Int("v", 0, "vCPU count")
|
serviceVcpu := serviceCmd.Int("v", 0, "vCPU count")
|
||||||
serviceKey := serviceCmd.String("k", "", "API key")
|
serviceKey := serviceCmd.String("k", "", "API key")
|
||||||
|
|
@ -684,7 +725,7 @@ func main() {
|
||||||
if vc == 0 {
|
if vc == 0 {
|
||||||
vc = *vcpu
|
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
|
return
|
||||||
|
|
||||||
case "key":
|
case "key":
|
||||||
|
|
|
||||||
46
un.js
46
un.js
|
|
@ -438,6 +438,34 @@ async function cmdService(args) {
|
||||||
return;
|
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) {
|
if (args.name) {
|
||||||
const payload = { name: args.name };
|
const payload = { name: args.name };
|
||||||
if (args.ports) payload.ports = args.ports.split(',').map(p => parseInt(p.trim()));
|
if (args.ports) payload.ports = args.ports.split(',').map(p => parseInt(p.trim()));
|
||||||
|
|
@ -494,6 +522,8 @@ function parseArgs(argv) {
|
||||||
destroy: null,
|
destroy: null,
|
||||||
execute: null,
|
execute: null,
|
||||||
command_arg: null,
|
command_arg: null,
|
||||||
|
dumpBootstrap: null,
|
||||||
|
dumpFile: null,
|
||||||
extend: false,
|
extend: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -570,10 +600,10 @@ function parseArgs(argv) {
|
||||||
} else if (arg === '--tail' && i + 1 < argv.length) {
|
} else if (arg === '--tail' && i + 1 < argv.length) {
|
||||||
args.tail = argv[++i];
|
args.tail = argv[++i];
|
||||||
i++;
|
i++;
|
||||||
} else if (arg === '--sleep' && i + 1 < argv.length) {
|
} else if (arg === '--freeze' && i + 1 < argv.length) {
|
||||||
args.sleep = argv[++i];
|
args.sleep = argv[++i];
|
||||||
i++;
|
i++;
|
||||||
} else if (arg === '--wake' && i + 1 < argv.length) {
|
} else if (arg === '--unfreeze' && i + 1 < argv.length) {
|
||||||
args.wake = argv[++i];
|
args.wake = argv[++i];
|
||||||
i++;
|
i++;
|
||||||
} else if (arg === '--destroy' && i + 1 < argv.length) {
|
} else if (arg === '--destroy' && i + 1 < argv.length) {
|
||||||
|
|
@ -585,6 +615,12 @@ function parseArgs(argv) {
|
||||||
} else if (arg === '--command' && i + 1 < argv.length) {
|
} else if (arg === '--command' && i + 1 < argv.length) {
|
||||||
args.command_arg = argv[++i];
|
args.command_arg = argv[++i];
|
||||||
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') {
|
} else if (arg === '--extend') {
|
||||||
args.extend = true;
|
args.extend = true;
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -648,11 +684,13 @@ Service options:
|
||||||
--info ID Get service details
|
--info ID Get service details
|
||||||
--logs ID Get all logs
|
--logs ID Get all logs
|
||||||
--tail ID Get last 9000 lines
|
--tail ID Get last 9000 lines
|
||||||
--sleep ID Freeze service
|
--freeze ID Freeze service
|
||||||
--wake ID Unfreeze service
|
--unfreeze ID Unfreeze service
|
||||||
--destroy ID Destroy service
|
--destroy ID Destroy service
|
||||||
--execute ID Execute command in service
|
--execute ID Execute command in service
|
||||||
--command CMD Command to execute (with --execute)
|
--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:
|
Key options:
|
||||||
--extend Open browser to extend key expiration
|
--extend Open browser to extend key expiration
|
||||||
|
|
|
||||||
47
un.lua
47
un.lua
|
|
@ -454,6 +454,35 @@ local function cmd_service(options)
|
||||||
return
|
return
|
||||||
end
|
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
|
if options.name then
|
||||||
local payload = { name = options.name }
|
local payload = { name = options.name }
|
||||||
if options.ports then
|
if options.ports then
|
||||||
|
|
@ -527,6 +556,8 @@ local function main()
|
||||||
destroy = nil,
|
destroy = nil,
|
||||||
execute = nil,
|
execute = nil,
|
||||||
command = nil,
|
command = nil,
|
||||||
|
dump_bootstrap = nil,
|
||||||
|
dump_file = nil,
|
||||||
extend = false
|
extend = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -597,10 +628,10 @@ local function main()
|
||||||
elseif a == "--tail" then
|
elseif a == "--tail" then
|
||||||
i = i + 1
|
i = i + 1
|
||||||
options.tail = arg[i]
|
options.tail = arg[i]
|
||||||
elseif a == "--sleep" then
|
elseif a == "--freeze" then
|
||||||
i = i + 1
|
i = i + 1
|
||||||
options.sleep = arg[i]
|
options.sleep = arg[i]
|
||||||
elseif a == "--wake" then
|
elseif a == "--unfreeze" then
|
||||||
i = i + 1
|
i = i + 1
|
||||||
options.wake = arg[i]
|
options.wake = arg[i]
|
||||||
elseif a == "--destroy" then
|
elseif a == "--destroy" then
|
||||||
|
|
@ -612,6 +643,12 @@ local function main()
|
||||||
elseif a == "--command" then
|
elseif a == "--command" then
|
||||||
i = i + 1
|
i = i + 1
|
||||||
options.command = arg[i]
|
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
|
elseif a == "--extend" then
|
||||||
options.extend = true
|
options.extend = true
|
||||||
elseif not a:match("^%-") then
|
elseif not a:match("^%-") then
|
||||||
|
|
@ -667,11 +704,13 @@ Service options:
|
||||||
--info ID Get service details
|
--info ID Get service details
|
||||||
--logs ID Get all logs
|
--logs ID Get all logs
|
||||||
--tail ID Get last 9000 lines
|
--tail ID Get last 9000 lines
|
||||||
--sleep ID Freeze service
|
--freeze ID Freeze service
|
||||||
--wake ID Unfreeze service
|
--unfreeze ID Unfreeze service
|
||||||
--destroy ID Destroy service
|
--destroy ID Destroy service
|
||||||
--execute ID Execute command in service
|
--execute ID Execute command in service
|
||||||
--command CMD Command to execute (with --execute)
|
--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:
|
Key options:
|
||||||
--extend Open browser to extend/renew key
|
--extend Open browser to extend/renew key
|
||||||
|
|
|
||||||
45
un.php
45
un.php
|
|
@ -436,6 +436,32 @@ function cmd_service($options) {
|
||||||
return;
|
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']) {
|
if ($options['name']) {
|
||||||
$payload = ['name' => $options['name']];
|
$payload = ['name' => $options['name']];
|
||||||
if ($options['ports']) {
|
if ($options['ports']) {
|
||||||
|
|
@ -500,6 +526,9 @@ function main() {
|
||||||
'wake' => null,
|
'wake' => null,
|
||||||
'destroy' => null,
|
'destroy' => null,
|
||||||
'execute' => null,
|
'execute' => null,
|
||||||
|
'command' => null,
|
||||||
|
'dump_bootstrap' => null,
|
||||||
|
'dump_file' => null,
|
||||||
'extend' => false
|
'extend' => false
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -580,10 +609,10 @@ function main() {
|
||||||
case '--tail':
|
case '--tail':
|
||||||
$options['tail'] = $argv[++$i];
|
$options['tail'] = $argv[++$i];
|
||||||
break;
|
break;
|
||||||
case '--sleep':
|
case '--freeze':
|
||||||
$options['sleep'] = $argv[++$i];
|
$options['sleep'] = $argv[++$i];
|
||||||
break;
|
break;
|
||||||
case '--wake':
|
case '--unfreeze':
|
||||||
$options['wake'] = $argv[++$i];
|
$options['wake'] = $argv[++$i];
|
||||||
break;
|
break;
|
||||||
case '--destroy':
|
case '--destroy':
|
||||||
|
|
@ -595,6 +624,12 @@ function main() {
|
||||||
case '--command':
|
case '--command':
|
||||||
$options['command'] = $argv[++$i];
|
$options['command'] = $argv[++$i];
|
||||||
break;
|
break;
|
||||||
|
case '--dump-bootstrap':
|
||||||
|
$options['dump_bootstrap'] = $argv[++$i];
|
||||||
|
break;
|
||||||
|
case '--dump-file':
|
||||||
|
$options['dump_file'] = $argv[++$i];
|
||||||
|
break;
|
||||||
case '--extend':
|
case '--extend':
|
||||||
$options['extend'] = true;
|
$options['extend'] = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -651,11 +686,13 @@ Service options:
|
||||||
--info ID Get service details
|
--info ID Get service details
|
||||||
--logs ID Get all logs
|
--logs ID Get all logs
|
||||||
--tail ID Get last 9000 lines
|
--tail ID Get last 9000 lines
|
||||||
--sleep ID Freeze service
|
--freeze ID Freeze service
|
||||||
--wake ID Unfreeze service
|
--unfreeze ID Unfreeze service
|
||||||
--destroy ID Destroy service
|
--destroy ID Destroy service
|
||||||
--execute ID Execute command in service
|
--execute ID Execute command in service
|
||||||
--command CMD Command to execute (with --execute)
|
--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:
|
Key options:
|
||||||
-k KEY API key (or use UNSANDBOX_API_KEY env var)
|
-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;
|
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}) {
|
if ($options->{name}) {
|
||||||
my $payload = { name => $options->{name} };
|
my $payload = { name => $options->{name} };
|
||||||
if ($options->{ports}) {
|
if ($options->{ports}) {
|
||||||
|
|
@ -462,6 +490,8 @@ sub main {
|
||||||
destroy => undef,
|
destroy => undef,
|
||||||
execute => undef,
|
execute => undef,
|
||||||
command => undef,
|
command => undef,
|
||||||
|
dump_bootstrap => undef,
|
||||||
|
dump_file => undef,
|
||||||
extend => 0
|
extend => 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -514,9 +544,9 @@ sub main {
|
||||||
$options{logs} = $ARGV[++$i];
|
$options{logs} = $ARGV[++$i];
|
||||||
} elsif ($arg eq '--tail') {
|
} elsif ($arg eq '--tail') {
|
||||||
$options{tail} = $ARGV[++$i];
|
$options{tail} = $ARGV[++$i];
|
||||||
} elsif ($arg eq '--sleep') {
|
} elsif ($arg eq '--freeze') {
|
||||||
$options{sleep} = $ARGV[++$i];
|
$options{sleep} = $ARGV[++$i];
|
||||||
} elsif ($arg eq '--wake') {
|
} elsif ($arg eq '--unfreeze') {
|
||||||
$options{wake} = $ARGV[++$i];
|
$options{wake} = $ARGV[++$i];
|
||||||
} elsif ($arg eq '--destroy') {
|
} elsif ($arg eq '--destroy') {
|
||||||
$options{destroy} = $ARGV[++$i];
|
$options{destroy} = $ARGV[++$i];
|
||||||
|
|
@ -524,6 +554,10 @@ sub main {
|
||||||
$options{execute} = $ARGV[++$i];
|
$options{execute} = $ARGV[++$i];
|
||||||
} elsif ($arg eq '--command') {
|
} elsif ($arg eq '--command') {
|
||||||
$options{command} = $ARGV[++$i];
|
$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') {
|
} elsif ($arg eq '--extend') {
|
||||||
$options{extend} = 1;
|
$options{extend} = 1;
|
||||||
} elsif ($arg !~ /^-/) {
|
} elsif ($arg !~ /^-/) {
|
||||||
|
|
@ -577,11 +611,13 @@ Service options:
|
||||||
--info ID Get service details
|
--info ID Get service details
|
||||||
--logs ID Get all logs
|
--logs ID Get all logs
|
||||||
--tail ID Get last 9000 lines
|
--tail ID Get last 9000 lines
|
||||||
--sleep ID Freeze service
|
--freeze ID Freeze service
|
||||||
--wake ID Unfreeze service
|
--unfreeze ID Unfreeze service
|
||||||
--destroy ID Destroy service
|
--destroy ID Destroy service
|
||||||
--execute ID Execute command in service
|
--execute ID Execute command in service
|
||||||
--command CMD Command to execute (with --execute)
|
--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:
|
Key options:
|
||||||
--extend Open browser to extend/renew key
|
--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)
|
print(f"{RED}{result['stderr']}{RESET}", end='', file=sys.stderr)
|
||||||
return
|
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
|
# Create new service
|
||||||
if args.name:
|
if args.name:
|
||||||
payload = {"name": 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("--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("--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("--logs", metavar="ID", help="Get all logs")
|
||||||
service_parser.add_argument("--sleep", metavar="ID", help="Freeze service")
|
service_parser.add_argument("--freeze", metavar="ID", help="Freeze service")
|
||||||
service_parser.add_argument("--wake", metavar="ID", help="Unfreeze 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("--destroy", metavar="ID", help="Destroy service")
|
||||||
service_parser.add_argument("--execute", metavar="ID", help="Execute command in 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("--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("-n", "--network", choices=["zerotrust", "semitrusted"])
|
||||||
service_parser.add_argument("-v", "--vcpu", type=int, choices=range(1, 9))
|
service_parser.add_argument("-v", "--vcpu", type=int, choices=range(1, 9))
|
||||||
service_parser.add_argument("-k", "--api-key")
|
service_parser.add_argument("-k", "--api-key")
|
||||||
|
|
|
||||||
46
un.rb
46
un.rb
|
|
@ -391,6 +391,34 @@ def cmd_service(options)
|
||||||
return
|
return
|
||||||
end
|
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]
|
if options[:name]
|
||||||
payload = { name: options[:name] }
|
payload = { name: options[:name] }
|
||||||
payload[:ports] = options[:ports].split(',').map(&:to_i) if options[:ports]
|
payload[:ports] = options[:ports].split(',').map(&:to_i) if options[:ports]
|
||||||
|
|
@ -447,6 +475,8 @@ def main
|
||||||
wake: nil,
|
wake: nil,
|
||||||
destroy: nil,
|
destroy: nil,
|
||||||
execute: nil,
|
execute: nil,
|
||||||
|
dump_bootstrap: nil,
|
||||||
|
dump_file: nil,
|
||||||
extend: false
|
extend: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -519,10 +549,10 @@ def main
|
||||||
when '--tail'
|
when '--tail'
|
||||||
i += 1
|
i += 1
|
||||||
options[:tail] = ARGV[i]
|
options[:tail] = ARGV[i]
|
||||||
when '--sleep'
|
when '--freeze'
|
||||||
i += 1
|
i += 1
|
||||||
options[:sleep] = ARGV[i]
|
options[:sleep] = ARGV[i]
|
||||||
when '--wake'
|
when '--unfreeze'
|
||||||
i += 1
|
i += 1
|
||||||
options[:wake] = ARGV[i]
|
options[:wake] = ARGV[i]
|
||||||
when '--destroy'
|
when '--destroy'
|
||||||
|
|
@ -534,6 +564,12 @@ def main
|
||||||
when '--command'
|
when '--command'
|
||||||
i += 1
|
i += 1
|
||||||
options[:command] = ARGV[i]
|
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'
|
when '--extend'
|
||||||
options[:extend] = true
|
options[:extend] = true
|
||||||
else
|
else
|
||||||
|
|
@ -591,11 +627,13 @@ def main
|
||||||
--info ID Get service details
|
--info ID Get service details
|
||||||
--logs ID Get all logs
|
--logs ID Get all logs
|
||||||
--tail ID Get last 9000 lines
|
--tail ID Get last 9000 lines
|
||||||
--sleep ID Freeze service
|
--freeze ID Freeze service
|
||||||
--wake ID Unfreeze service
|
--unfreeze ID Unfreeze service
|
||||||
--destroy ID Destroy service
|
--destroy ID Destroy service
|
||||||
--execute ID Execute command in service
|
--execute ID Execute command in service
|
||||||
--command CMD Command to execute (with --execute)
|
--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:
|
Key options:
|
||||||
-k KEY API key (or use UNSANDBOX_API_KEY env var)
|
-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"
|
tail="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
--sleep)
|
--freeze)
|
||||||
sleep="$2"
|
sleep="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
--wake)
|
--unfreeze)
|
||||||
wake="$2"
|
wake="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
|
@ -469,6 +469,14 @@ cmd_service() {
|
||||||
command="$2"
|
command="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--dump-bootstrap)
|
||||||
|
dump_bootstrap="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--dump-file)
|
||||||
|
dump_file="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
-n)
|
-n)
|
||||||
network="$2"
|
network="$2"
|
||||||
shift 2
|
shift 2
|
||||||
|
|
@ -548,6 +556,29 @@ cmd_service() {
|
||||||
return
|
return
|
||||||
fi
|
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
|
if [[ -n "$name" ]]; then
|
||||||
local payload=$(jq -n --arg n "$name" '{name: $n}')
|
local payload=$(jq -n --arg n "$name" '{name: $n}')
|
||||||
|
|
||||||
|
|
@ -774,11 +805,13 @@ Service options:
|
||||||
--info ID Get service details
|
--info ID Get service details
|
||||||
--logs ID Get all logs
|
--logs ID Get all logs
|
||||||
--tail ID Get last 9000 lines
|
--tail ID Get last 9000 lines
|
||||||
--sleep ID Freeze service
|
--freeze ID Freeze service
|
||||||
--wake ID Unfreeze service
|
--unfreeze ID Unfreeze service
|
||||||
--destroy ID Destroy service
|
--destroy ID Destroy service
|
||||||
--execute ID Execute command in service
|
--execute ID Execute command in service
|
||||||
--command CMD Command to execute (with --execute)
|
--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:
|
Key options:
|
||||||
-k KEY API key to validate
|
-k KEY API key to validate
|
||||||
|
|
|
||||||
46
un.ts
46
un.ts
|
|
@ -393,6 +393,34 @@ async function cmdService(args: Args): Promise<void> {
|
||||||
return;
|
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) {
|
if (args.name) {
|
||||||
const payload: any = { name: args.name };
|
const payload: any = { name: args.name };
|
||||||
if (args.ports) payload.ports = args.ports.split(',').map(p => parseInt(p.trim()));
|
if (args.ports) payload.ports = args.ports.split(',').map(p => parseInt(p.trim()));
|
||||||
|
|
@ -520,6 +548,8 @@ function parseArgs(argv: string[]): Args {
|
||||||
destroy: null,
|
destroy: null,
|
||||||
execute: null,
|
execute: null,
|
||||||
command_arg: null,
|
command_arg: null,
|
||||||
|
dumpBootstrap: null,
|
||||||
|
dumpFile: null,
|
||||||
extend: false,
|
extend: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -596,10 +626,10 @@ function parseArgs(argv: string[]): Args {
|
||||||
} else if (arg === '--tail' && i + 1 < argv.length) {
|
} else if (arg === '--tail' && i + 1 < argv.length) {
|
||||||
args.tail = argv[++i];
|
args.tail = argv[++i];
|
||||||
i++;
|
i++;
|
||||||
} else if (arg === '--sleep' && i + 1 < argv.length) {
|
} else if (arg === '--freeze' && i + 1 < argv.length) {
|
||||||
args.sleep = argv[++i];
|
args.sleep = argv[++i];
|
||||||
i++;
|
i++;
|
||||||
} else if (arg === '--wake' && i + 1 < argv.length) {
|
} else if (arg === '--unfreeze' && i + 1 < argv.length) {
|
||||||
args.wake = argv[++i];
|
args.wake = argv[++i];
|
||||||
i++;
|
i++;
|
||||||
} else if (arg === '--destroy' && i + 1 < argv.length) {
|
} 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) {
|
} else if (arg === '--command' && i + 1 < argv.length) {
|
||||||
args.command_arg = argv[++i];
|
args.command_arg = argv[++i];
|
||||||
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') {
|
} else if (arg === '--extend') {
|
||||||
args.extend = true;
|
args.extend = true;
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -674,11 +710,13 @@ Service options:
|
||||||
--info ID Get service details
|
--info ID Get service details
|
||||||
--logs ID Get all logs
|
--logs ID Get all logs
|
||||||
--tail ID Get last 9000 lines
|
--tail ID Get last 9000 lines
|
||||||
--sleep ID Freeze service
|
--freeze ID Freeze service
|
||||||
--wake ID Unfreeze service
|
--unfreeze ID Unfreeze service
|
||||||
--destroy ID Destroy service
|
--destroy ID Destroy service
|
||||||
--execute ID Execute command in service
|
--execute ID Execute command in service
|
||||||
--command CMD Command to execute (with --execute)
|
--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:
|
Key options:
|
||||||
--extend Open browser to extend key expiration
|
--extend Open browser to extend key expiration
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue