vmsan 0.1.0-alpha.17 → 0.1.0-alpha.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -106,6 +106,12 @@ vmsan create --from-image node:22-alpine
106
106
  # List all VMs
107
107
  vmsan list
108
108
 
109
+ # Execute a command inside a VM
110
+ vmsan exec <vm-id> ls -la
111
+
112
+ # Interactive exec with PTY
113
+ vmsan exec -i <vm-id> bash
114
+
109
115
  # Connect to a running VM shell
110
116
  vmsan connect <vm-id>
111
117
 
@@ -131,16 +137,17 @@ vmsan remove <vm-id>
131
137
 
132
138
  ### Commands
133
139
 
134
- | Command | Alias | Description |
135
- | ---------- | ----- | --------------------------------- |
136
- | `create` | | Create and start a new microVM |
137
- | `list` | `ls` | List all VMs |
138
- | `start` | | Start a stopped VM |
139
- | `stop` | | Stop a running VM |
140
- | `remove` | `rm` | Remove a VM |
141
- | `connect` | | Open an interactive shell to a VM |
142
- | `upload` | | Upload files to a VM |
143
- | `download` | | Download files from a VM |
140
+ | Command | Alias | Description |
141
+ | ---------- | ----- | ------------------------------------ |
142
+ | `create` | | Create and start a new microVM |
143
+ | `list` | `ls` | List all VMs |
144
+ | `start` | | Start a stopped VM |
145
+ | `stop` | | Stop a running VM |
146
+ | `remove` | `rm` | Remove a VM |
147
+ | `exec` | | Execute a command inside a running VM |
148
+ | `connect` | | Open an interactive shell to a VM |
149
+ | `upload` | | Upload files to a VM |
150
+ | `download` | | Download files from a VM |
144
151
 
145
152
  ## Development
146
153
 
@@ -1333,6 +1333,7 @@ function generateAgentEnv(token, port, vmId) {
1333
1333
  return `VMSAN_AGENT_TOKEN=${token}
1334
1334
  VMSAN_AGENT_PORT=${port}
1335
1335
  VMSAN_VM_ID=${vmId}
1336
+ VMSAN_DEFAULT_USER=ubuntu
1336
1337
  `;
1337
1338
  }
1338
1339
  /**
@@ -1627,6 +1628,7 @@ const APT_PACKAGES = [
1627
1628
  "openssh-server",
1628
1629
  "openssl",
1629
1630
  "procps",
1631
+ "sudo",
1630
1632
  "tar",
1631
1633
  "unzip",
1632
1634
  "debianutils",
@@ -1648,6 +1650,7 @@ const DNF_PACKAGES = [
1648
1650
  "openssl",
1649
1651
  "openssl-libs",
1650
1652
  "procps",
1653
+ "sudo",
1651
1654
  "tar",
1652
1655
  "unzip",
1653
1656
  "which",
@@ -1655,6 +1658,7 @@ const DNF_PACKAGES = [
1655
1658
  "zstd"
1656
1659
  ];
1657
1660
  const APK_PACKAGES = [
1661
+ "bash",
1658
1662
  "bind-tools",
1659
1663
  "bzip2",
1660
1664
  "findutils",
@@ -1669,6 +1673,7 @@ const APK_PACKAGES = [
1669
1673
  "openssh",
1670
1674
  "openssl",
1671
1675
  "procps",
1676
+ "sudo",
1672
1677
  "tar",
1673
1678
  "unzip",
1674
1679
  "whois",
@@ -1681,6 +1686,14 @@ RUN if command -v apt-get >/dev/null 2>&1; then ${`apt-get update && apt-get ins
1681
1686
  elif command -v yum >/dev/null 2>&1; then ${`yum install -y ${DNF_PACKAGES.join(" ")} && yum clean all`}; \\
1682
1687
  elif command -v apk >/dev/null 2>&1; then ${`apk add --no-cache ${APK_PACKAGES.join(" ")}`}; \\
1683
1688
  fi
1689
+ RUN if command -v apk >/dev/null 2>&1; then \\
1690
+ id -u ubuntu >/dev/null 2>&1 || adduser -D -s /bin/bash ubuntu; \\
1691
+ else \\
1692
+ id -u ubuntu >/dev/null 2>&1 || useradd -m -s /bin/bash ubuntu; \\
1693
+ fi; \\
1694
+ echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/ubuntu; \\
1695
+ chmod 440 /etc/sudoers.d/ubuntu; \\
1696
+ mkdir -p /home/ubuntu/.ssh && chown -R ubuntu:ubuntu /home/ubuntu
1684
1697
  RUN ssh-keygen -A 2>/dev/null || true; \\
1685
1698
  mkdir -p /root/.ssh && chmod 700 /root/.ssh; \\
1686
1699
  if [ -f /etc/ssh/sshd_config ]; then \\
@@ -113,7 +113,6 @@ const execCommand = defineCommand({
113
113
  parts.push(`export PS1=${shellEscape(buildVmsanPrompt(args.vmId))} TERM=xterm-256color &&`);
114
114
  if (args.workdir) parts.push(`cd ${shellEscape(args.workdir)} &&`);
115
115
  for (const [key, val] of Object.entries(envVars)) parts.push(`${key}=${shellEscape(val)}`);
116
- if (args.sudo) parts.push("/usr/bin/sudo");
117
116
  parts.push(shellEscape(command));
118
117
  for (const a of commandArgs) parts.push(shellEscape(a));
119
118
  const injectedCmd = "clear; " + parts.join(" ") + "; exit $?\n";
@@ -131,7 +130,8 @@ const execCommand = defineCommand({
131
130
  host: guestIp,
132
131
  port,
133
132
  token: state.agentToken,
134
- initialCommand: injectedCmd
133
+ initialCommand: injectedCmd,
134
+ user: args.sudo ? "root" : void 0
135
135
  }).connect();
136
136
  } finally {
137
137
  extender?.stop();
@@ -147,13 +147,12 @@ const execCommand = defineCommand({
147
147
  } else {
148
148
  consola.debug(`exec: ${command} ${commandArgs.join(" ")}`);
149
149
  const agent = new AgentClient(`http://${guestIp}:${port}`, state.agentToken);
150
- const cmd = args.sudo ? "/usr/bin/sudo" : command;
151
- const runArgs = args.sudo ? [command, ...commandArgs] : commandArgs;
152
150
  const params = {
153
- cmd,
154
- args: runArgs.length > 0 ? runArgs : void 0,
151
+ cmd: command,
152
+ args: commandArgs.length > 0 ? commandArgs : void 0,
155
153
  cwd: args.workdir || void 0,
156
- env: Object.keys(envVars).length > 0 ? envVars : void 0
154
+ env: Object.keys(envVars).length > 0 ? envVars : void 0,
155
+ user: args.sudo ? "root" : void 0
157
156
  };
158
157
  const ac = new AbortController();
159
158
  const onSignal = () => ac.abort();
@@ -137,6 +137,7 @@ var ShellSession = class {
137
137
  const url = new URL(`${proto}://${this.opts.host}:${this.opts.port}/ws/shell`);
138
138
  url.searchParams.set("token", this.opts.token);
139
139
  if (this.opts.shell) url.searchParams.set("shell", this.opts.shell);
140
+ if (this.opts.user) url.searchParams.set("user", this.opts.user);
140
141
  return url.toString();
141
142
  }
142
143
  };
package/dist/index.d.mts CHANGED
@@ -2857,6 +2857,7 @@ interface RunParams {
2857
2857
  env?: Record<string, string>;
2858
2858
  timeoutMs?: number;
2859
2859
  detached?: boolean;
2860
+ user?: string;
2860
2861
  }
2861
2862
  type RunEventType = "started" | "stdout" | "stderr" | "exit" | "timeout" | "error";
2862
2863
  interface RunEvent {
@@ -3043,6 +3044,7 @@ interface ShellSessionOptions {
3043
3044
  shell?: string;
3044
3045
  sessionId?: string;
3045
3046
  initialCommand?: string;
3047
+ user?: string;
3046
3048
  }
3047
3049
  interface ShellCloseInfo {
3048
3050
  /** true when the shell process exited (e.g. user typed `exit`) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vmsan",
3
- "version": "0.1.0-alpha.17",
3
+ "version": "0.1.0-alpha.19",
4
4
  "description": "Firecracker microVM sandbox toolkit",
5
5
  "homepage": "https://github.com/angelorc/vmsan",
6
6
  "bugs": "https://github.com/angelorc/vmsan/issues",