Merge nucleic/lucid-river-toad-6efj into dev
This commit is contained in:
+24
-10
@@ -36,6 +36,10 @@ internal static class Program
|
|||||||
var iterations = int.TryParse(Arg(args, "--iterations"), out var n) ? n : 5;
|
var iterations = int.TryParse(Arg(args, "--iterations"), out var n) ? n : 5;
|
||||||
var broker = Arg(args, "--broker") ?? FindBroker();
|
var broker = Arg(args, "--broker") ?? FindBroker();
|
||||||
var skipRecovery = args.Contains("--no-recovery");
|
var skipRecovery = args.Contains("--no-recovery");
|
||||||
|
// narOS runs `naros-init` as PID 1 and stays up (docs/NAROS.md). A stock image usually
|
||||||
|
// does not: alpine's PID 1 is /bin/sh, which exits immediately with no tty, so the
|
||||||
|
// container is `Exited` before the first exec and every later step fails `not_running`.
|
||||||
|
var sleepInit = args.Contains("--sleep-init");
|
||||||
|
|
||||||
if (broker is null || !File.Exists(broker))
|
if (broker is null || !File.Exists(broker))
|
||||||
{
|
{
|
||||||
@@ -53,7 +57,7 @@ internal static class Program
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await RunScenarioAsync(broker, sessionName, image, container, repo, iterations);
|
await RunScenarioAsync(broker, sessionName, image, container, repo, iterations, sleepInit);
|
||||||
if (!skipRecovery) await RunRecoveryAsync(broker, sessionName);
|
if (!skipRecovery) await RunRecoveryAsync(broker, sessionName);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -69,7 +73,7 @@ internal static class Program
|
|||||||
|
|
||||||
private static async Task RunScenarioAsync(
|
private static async Task RunScenarioAsync(
|
||||||
string brokerPath, string sessionName, string image, string containerName,
|
string brokerPath, string sessionName, string image, string containerName,
|
||||||
string repo, int iterations)
|
string repo, int iterations, bool sleepInit)
|
||||||
{
|
{
|
||||||
await using var broker = BrokerClient.Spawn(brokerPath);
|
await using var broker = BrokerClient.Spawn(brokerPath);
|
||||||
|
|
||||||
@@ -131,19 +135,29 @@ internal static class Program
|
|||||||
Console.WriteLine($" pulled in {pullWatch.Elapsed.TotalSeconds:F1}s");
|
Console.WriteLine($" pulled in {pullWatch.Elapsed.TotalSeconds:F1}s");
|
||||||
|
|
||||||
Step($"container.create {containerName}");
|
Step($"container.create {containerName}");
|
||||||
await broker.CallAsync("container.create", new
|
var create = new Dictionary<string, object?>
|
||||||
{
|
{
|
||||||
name = containerName,
|
["name"] = containerName,
|
||||||
image,
|
["image"] = image,
|
||||||
volumes = new[] { new { host = repo, guest = "/work", ro = false } },
|
["volumes"] = new[] { new { host = repo, guest = "/work", ro = false } },
|
||||||
networkingMode = "Bridged",
|
["networkingMode"] = "Bridged",
|
||||||
hostname = "nucleic-spike",
|
["hostname"] = "nucleic-spike",
|
||||||
env = new Dictionary<string, string> { ["NUCLEIC_SPIKE"] = "1" },
|
["env"] = new Dictionary<string, string> { ["NUCLEIC_SPIKE"] = "1" },
|
||||||
});
|
};
|
||||||
|
if (sleepInit) create["initArgv"] = new[] { "/bin/sh", "-c", "sleep 3600" };
|
||||||
|
await broker.CallAsync("container.create", create);
|
||||||
await broker.CallAsync("container.start", new { name = containerName });
|
await broker.CallAsync("container.start", new { name = containerName });
|
||||||
var state = (await broker.CallAsync("container.state", new { name = containerName }))
|
var state = (await broker.CallAsync("container.state", new { name = containerName }))
|
||||||
.GetProperty("state").GetString();
|
.GetProperty("state").GetString();
|
||||||
Console.WriteLine($" state: {state}");
|
Console.WriteLine($" state: {state}");
|
||||||
|
// Check here rather than letting the first exec fail `not_running`: a container whose
|
||||||
|
// PID 1 exited looks identical to a container that failed to start, and the remedy
|
||||||
|
// (supply a long-running init) is nothing like the remedy for a real start failure.
|
||||||
|
if (state != "running")
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"container is '{state}' immediately after start — its PID 1 exited. narOS runs "
|
||||||
|
+ "naros-init and stays up; a stock image (alpine's PID 1 is /bin/sh) does not. "
|
||||||
|
+ "Re-run with --sleep-init to give it a long-running init process.");
|
||||||
|
|
||||||
Step("exec: stdio round-trip");
|
Step("exec: stdio round-trip");
|
||||||
var (code, output) = await ExecAsync(broker, containerName, ["/bin/sh", "-c", "echo hello from \"$(uname -n)\"; echo to-stderr 1>&2"]);
|
var (code, output) = await ExecAsync(broker, containerName, ["/bin/sh", "-c", "echo hello from \"$(uname -n)\"; echo to-stderr 1>&2"]);
|
||||||
|
|||||||
Reference in New Issue
Block a user