microsandbox-rb 0.5.8 → 0.5.10

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.
@@ -0,0 +1,247 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Microsandbox
4
+ # The result of an {SshClient#exec} call. Like {ExecOutput}, `stdout`/`stderr`
5
+ # are the captured bytes decoded as UTF-8 (lenient); use `stdout_bytes`/
6
+ # `stderr_bytes` for the raw ASCII-8BIT bytes.
7
+ class SshOutput
8
+ # @return [Integer] the remote command's exit status
9
+ attr_reader :status
10
+ # @return [String] raw stdout bytes (ASCII-8BIT)
11
+ attr_reader :stdout_bytes
12
+ # @return [String] raw stderr bytes (ASCII-8BIT)
13
+ attr_reader :stderr_bytes
14
+
15
+ def initialize(data)
16
+ @status = data["status"]
17
+ @success = data["success"]
18
+ @stdout_bytes = data["stdout"]
19
+ @stderr_bytes = data["stderr"]
20
+ end
21
+
22
+ # @return [Boolean] whether the command exited with status 0
23
+ def success? = @success
24
+
25
+ # @return [Boolean] whether the command exited non-zero
26
+ def failure? = !@success
27
+
28
+ # @return [String] stdout decoded as UTF-8
29
+ def stdout
30
+ @stdout ||= @stdout_bytes.dup.force_encoding(Encoding::UTF_8)
31
+ end
32
+
33
+ # @return [String] stderr decoded as UTF-8
34
+ def stderr
35
+ @stderr ||= @stderr_bytes.dup.force_encoding(Encoding::UTF_8)
36
+ end
37
+
38
+ def to_s = stdout
39
+
40
+ def inspect
41
+ "#<Microsandbox::SshOutput status=#{@status} success=#{@success} " \
42
+ "stdout=#{stdout.bytesize}B stderr=#{stderr.bytesize}B>"
43
+ end
44
+ end
45
+
46
+ # A high-level SFTP session over an {SshClient}, from {SshClient#sftp}. All
47
+ # paths are guest paths. Mirrors the `SftpClient` of the official SDKs.
48
+ class SftpClient
49
+ def initialize(native)
50
+ @native = native
51
+ end
52
+
53
+ # Read a file's full contents.
54
+ # @return [String] raw bytes (ASCII-8BIT)
55
+ def read(path)
56
+ @native.read(path.to_s)
57
+ end
58
+
59
+ # Read a file and decode it as UTF-8 (lenient).
60
+ # @return [String]
61
+ def read_text(path)
62
+ read(path).force_encoding(Encoding::UTF_8)
63
+ end
64
+
65
+ # Write a file, creating or truncating it.
66
+ # @return [nil]
67
+ def write(path, data)
68
+ @native.write(path.to_s, data.to_s)
69
+ nil
70
+ end
71
+
72
+ # Create a directory.
73
+ # @return [nil]
74
+ def mkdir(path)
75
+ @native.mkdir(path.to_s)
76
+ nil
77
+ end
78
+
79
+ # Remove a file.
80
+ # @return [nil]
81
+ def remove_file(path)
82
+ @native.remove_file(path.to_s)
83
+ nil
84
+ end
85
+
86
+ # Remove an empty directory.
87
+ # @return [nil]
88
+ def remove_dir(path)
89
+ @native.remove_dir(path.to_s)
90
+ nil
91
+ end
92
+
93
+ # Rename (move) a file or directory.
94
+ # @return [nil]
95
+ def rename(old_path, new_path)
96
+ @native.rename(old_path.to_s, new_path.to_s)
97
+ nil
98
+ end
99
+
100
+ # Create a symlink at +link_path+ pointing to +target+.
101
+ # @return [nil]
102
+ def symlink(target, link_path)
103
+ @native.symlink(target.to_s, link_path.to_s)
104
+ nil
105
+ end
106
+
107
+ # Resolve a path to its canonical absolute form.
108
+ # @return [String]
109
+ def real_path(path)
110
+ @native.real_path(path.to_s)
111
+ end
112
+
113
+ # Read a symlink's target.
114
+ # @return [String]
115
+ def read_link(path)
116
+ @native.read_link(path.to_s)
117
+ end
118
+
119
+ # Close the SFTP session. Idempotent.
120
+ # @return [nil]
121
+ def close
122
+ @native.close
123
+ nil
124
+ end
125
+ end
126
+
127
+ # A native, in-process SSH client session to a sandbox, from
128
+ # {SshOps#open_client}. Mirrors the `SshClient` of the official SDKs.
129
+ #
130
+ # @example
131
+ # sb.ssh.open_client do |client|
132
+ # out = client.exec("uname -a")
133
+ # puts out.stdout
134
+ # end
135
+ class SshClient
136
+ def initialize(native)
137
+ @native = native
138
+ end
139
+
140
+ # Run a command over SSH and collect its output.
141
+ # @param command [String] the command line (interpreted by the remote shell)
142
+ # @param tty [Boolean] allocate a pseudo-terminal
143
+ # @return [SshOutput]
144
+ def exec(command, tty: false)
145
+ SshOutput.new(@native.exec(command.to_s, tty ? true : false))
146
+ end
147
+
148
+ # Attach the local terminal to an interactive SSH shell. Host-TTY coupled
149
+ # (puts the terminal in raw mode and forwards SIGWINCH); blocks until the
150
+ # remote shell exits or the detach sequence is typed.
151
+ # @param term [String, nil] TERM value to request (defaults to $TERM)
152
+ # @param detach_keys [String, nil] detach key sequence (e.g. "ctrl-p,ctrl-q")
153
+ # @return [Integer] the remote shell's exit status
154
+ def attach(term: nil, detach_keys: nil)
155
+ @native.attach(term&.to_s, detach_keys&.to_s)
156
+ end
157
+
158
+ # Open an SFTP session over this connection. With a block, the session is
159
+ # yielded and closed when the block returns.
160
+ # @yieldparam sftp [SftpClient]
161
+ # @return [SftpClient, Object]
162
+ def sftp
163
+ session = SftpClient.new(@native.sftp)
164
+ return session unless block_given?
165
+
166
+ begin
167
+ yield session
168
+ ensure
169
+ session.close
170
+ end
171
+ end
172
+
173
+ # Close the SSH client session. Idempotent.
174
+ # @return [nil]
175
+ def close
176
+ @native.close
177
+ nil
178
+ end
179
+ end
180
+
181
+ # A reusable SSH server endpoint for a sandbox, from {SshOps#prepare_server}.
182
+ # Each {#serve_connection} serves a single SSH transport over this process's
183
+ # stdin/stdout — typically wired up by a parent SSH daemon via `ForceCommand`
184
+ # or an inetd-style spawn. Mirrors the `SshServer` of the official SDKs.
185
+ class SshServer
186
+ def initialize(native)
187
+ @native = native
188
+ end
189
+
190
+ # Serve one SSH connection over this process's stdin/stdout. Blocks until
191
+ # the session ends.
192
+ # @return [nil]
193
+ def serve_connection
194
+ @native.serve_connection
195
+ nil
196
+ end
197
+
198
+ # Release the prepared server endpoint. Idempotent.
199
+ # @return [nil]
200
+ def close
201
+ @native.close
202
+ nil
203
+ end
204
+ end
205
+
206
+ # The SSH namespace for a sandbox, returned by {Sandbox#ssh}. Use it to open a
207
+ # native in-process SSH client or prepare a reusable server endpoint.
208
+ class SshOps
209
+ def initialize(native)
210
+ @native = native
211
+ end
212
+
213
+ # Open a native in-process SSH client to the sandbox. With a block, the
214
+ # client is yielded and closed when the block returns.
215
+ # @param user [String] guest user to authenticate as (default "root")
216
+ # @param term [String, nil] TERM value for the session
217
+ # @param sftp [Boolean] enable the SFTP subsystem (default true)
218
+ # @yieldparam client [SshClient]
219
+ # @return [SshClient, Object]
220
+ def open_client(user: "root", term: nil, sftp: true)
221
+ opts = {"user" => user.to_s, "sftp" => sftp ? true : false}
222
+ opts["term"] = term.to_s if term
223
+ client = SshClient.new(@native.ssh_open_client(opts))
224
+ return client unless block_given?
225
+
226
+ begin
227
+ yield client
228
+ ensure
229
+ client.close
230
+ end
231
+ end
232
+
233
+ # Prepare a reusable SSH server endpoint for the sandbox.
234
+ # @param host_key_path [String, nil] PEM host key path (generated if omitted)
235
+ # @param authorized_keys_path [String, nil] authorized_keys file path
236
+ # @param user [String, nil] guest user connections run as
237
+ # @param sftp [Boolean] enable the SFTP subsystem (default true)
238
+ # @return [SshServer]
239
+ def prepare_server(host_key_path: nil, authorized_keys_path: nil, user: nil, sftp: true)
240
+ opts = {"sftp" => sftp ? true : false}
241
+ opts["host_key_path"] = host_key_path.to_s if host_key_path
242
+ opts["authorized_keys_path"] = authorized_keys_path.to_s if authorized_keys_path
243
+ opts["user"] = user.to_s if user
244
+ SshServer.new(@native.ssh_prepare_server(opts))
245
+ end
246
+ end
247
+ end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Microsandbox
4
- # Gem version. Tracks the upstream microsandbox runtime (currently `v0.5.7`,
4
+ # Gem version. Tracks the upstream microsandbox runtime (currently `v0.5.8`,
5
5
  # the pinned core-crate tag); the patch segment advances for gem-only revisions
6
6
  # that add bindings atop the same core. Must equal the native ext's Cargo crate
7
7
  # version (`Native.version`), enforced by spec/unit/version_spec.rb.
8
- VERSION = "0.5.8"
8
+ VERSION = "0.5.10"
9
9
  end
@@ -7,7 +7,7 @@ module Microsandbox
7
7
  # (`kind`, `used_bytes`, …) are populated when returned from {Volume.get}/{Volume.list}.
8
8
  class VolumeInfo
9
9
  attr_reader :name, :path, :quota_mib, :used_bytes, :capacity_bytes,
10
- :disk_format, :disk_fstype, :labels
10
+ :disk_format, :disk_fstype, :labels
11
11
 
12
12
  def initialize(data)
13
13
  @name = data["name"]
@@ -33,7 +33,7 @@ module Microsandbox
33
33
  end
34
34
 
35
35
  def inspect
36
- "#<Microsandbox::VolumeInfo name=#{@name.inspect}#{@kind ? " kind=#{@kind}" : ""}>"
36
+ "#<Microsandbox::VolumeInfo name=#{@name.inspect}#{" kind=#{@kind}" if @kind}>"
37
37
  end
38
38
  end
39
39
 
@@ -49,7 +49,7 @@ module Microsandbox
49
49
  # @param labels [Hash, nil]
50
50
  # @return [VolumeInfo]
51
51
  def create(name, kind: "dir", size_mib: nil, quota_mib: nil, labels: nil)
52
- opts = { "kind" => kind.to_s }
52
+ opts = {"kind" => kind.to_s}
53
53
  opts["size_mib"] = Integer(size_mib) if size_mib
54
54
  opts["quota_mib"] = Integer(quota_mib) if quota_mib
55
55
  opts["labels"] = labels.each_with_object({}) { |(k, v), a| a[k.to_s] = v.to_s } if labels
data/lib/microsandbox.rb CHANGED
@@ -22,6 +22,10 @@ require_relative "microsandbox/streams"
22
22
  require_relative "microsandbox/image"
23
23
  require_relative "microsandbox/volume"
24
24
  require_relative "microsandbox/snapshot"
25
+ require_relative "microsandbox/patch"
26
+ require_relative "microsandbox/network"
27
+ require_relative "microsandbox/agent"
28
+ require_relative "microsandbox/ssh"
25
29
  require_relative "microsandbox/sandbox"
26
30
 
27
31
  # Microsandbox — lightweight microVM sandboxes for Ruby.
@@ -74,6 +78,11 @@ module Microsandbox
74
78
  # @return [nil]
75
79
  def ensure_runtime!
76
80
  return if @runtime_ready
81
+ # A cloud backend has no local msb/libkrunfw runtime to provision: skip the
82
+ # presence check and the first-use download entirely. Resolving the kind
83
+ # uses the same lazy env/profile/config ladder every operation already
84
+ # consults, so this adds no work for local hosts (the common case).
85
+ return if default_backend_kind == :cloud
77
86
  if installed?
78
87
  @runtime_ready = true
79
88
  return
@@ -100,6 +109,62 @@ module Microsandbox
100
109
  Native.set_runtime_msb_path(path.to_s)
101
110
  end
102
111
 
112
+ # Override the `libkrunfw` shared-library path (SDK tier of the resolver,
113
+ # below the `MSB_LIBKRUNFW_PATH` environment variable). Process-level and
114
+ # set-once: a second call is silently ignored, and the env var still wins.
115
+ # Mirrors {runtime_path=} for libkrunfw.
116
+ # @param path [String]
117
+ # @return [void]
118
+ def libkrunfw_path=(path)
119
+ Native.set_runtime_libkrunfw_path(path.to_s)
120
+ end
121
+
122
+ # Install a process-wide default backend (v0.5.8 backend routing). Without a
123
+ # call to this, operations use a local libkrun backend; the env/profile
124
+ # ladder (`MSB_BACKEND`, `MSB_API_URL`+`MSB_API_KEY`, `MSB_PROFILE`,
125
+ # `~/.microsandbox/config.json`) is resolved lazily on first use. Call once
126
+ # at startup, before any sandbox operations.
127
+ #
128
+ # @param kind ["local","cloud", Symbol] backend kind
129
+ # @param url [String, nil] cloud control-plane URL (cloud, unless `profile:`)
130
+ # @param api_key [String, nil] cloud API key (cloud, unless `profile:`)
131
+ # @param profile [String, nil] named profile from `~/.microsandbox/config.json`
132
+ # @return [void]
133
+ def set_default_backend(kind, url: nil, api_key: nil, profile: nil)
134
+ Native.set_default_backend(kind.to_s, url&.to_s, api_key&.to_s, profile&.to_s)
135
+ end
136
+
137
+ # Run the given block with a temporary default backend, restoring the
138
+ # previous one afterward (even on error). NOTE: the swap is process-wide
139
+ # while the block runs, not fiber/thread-local — concurrent threads observe
140
+ # the temporary backend. It is also NOT safe to call from multiple threads
141
+ # at once: two interleaved `with_backend` calls can restore each other's
142
+ # saved backend out of order and leave a temporary backend installed
143
+ # permanently. Use it only when no other thread is changing the backend, and
144
+ # avoid calling {set_default_backend} inside the block (the restore on exit
145
+ # would overwrite that change). Mirrors the official SDKs' scoped-backend helper.
146
+ #
147
+ # @param kind ["local","cloud", Symbol]
148
+ # @param url [String, nil]
149
+ # @param api_key [String, nil]
150
+ # @param profile [String, nil]
151
+ # @yield with the temporary backend installed
152
+ # @return [Object] the block's return value
153
+ def with_backend(kind, url: nil, api_key: nil, profile: nil)
154
+ token = Native.push_default_backend(kind.to_s, url&.to_s, api_key&.to_s, profile&.to_s)
155
+ begin
156
+ yield
157
+ ensure
158
+ Native.pop_default_backend(token)
159
+ end
160
+ end
161
+
162
+ # @return [Symbol] the active default backend kind, :local or :cloud.
163
+ # The first call resolves the env/profile/config ladder.
164
+ def default_backend_kind
165
+ Native.default_backend_kind.to_sym
166
+ end
167
+
103
168
  # Latest resource-usage snapshot for every running sandbox, keyed by name.
104
169
  # Mirrors the official `all_sandbox_metrics`/`allSandboxMetrics` helpers.
105
170
  # @return [Hash{String => Metrics}]
data/sig/microsandbox.rbs CHANGED
@@ -9,8 +9,13 @@ module Microsandbox
9
9
  def self.ensure_runtime!: () -> nil
10
10
  def self.runtime_path: () -> String
11
11
  def self.runtime_path=: (String path) -> void
12
+ def self.libkrunfw_path=: (String path) -> void
12
13
  def self.all_sandbox_metrics: () -> Hash[String, Metrics]
13
14
 
15
+ def self.set_default_backend: (String | Symbol kind, ?url: String?, ?api_key: String?, ?profile: String?) -> void
16
+ def self.with_backend: [T] (String | Symbol kind, ?url: String?, ?api_key: String?, ?profile: String?) { () -> T } -> T
17
+ def self.default_backend_kind: () -> Symbol
18
+
14
19
  class Error < StandardError
15
20
  def self.code: () -> String
16
21
  def code: () -> String
@@ -37,6 +42,8 @@ module Microsandbox
37
42
  class MetricsDisabledError < Error end
38
43
  class MetricsUnavailableError < Error end
39
44
  class UnsupportedOperationError < Error end
45
+ class CloudHttpError < Error end
46
+ class UnsupportedError < Error end
40
47
 
41
48
  class ExecOutput
42
49
  def initialize: (Hash[String, untyped] data) -> void
@@ -114,15 +121,26 @@ module Microsandbox
114
121
  def timestamp: () -> Time
115
122
  end
116
123
 
117
- class SandboxInfo
124
+ class SandboxHandle
118
125
  def name: () -> String
119
126
  def status: () -> Symbol
120
127
  def running?: () -> bool
121
128
  def stopped?: () -> bool
122
129
  def created_at: () -> Time?
123
130
  def updated_at: () -> Time?
131
+ def stop: () -> nil
132
+ def stop_with_timeout: (Numeric timeout) -> nil
133
+ def kill: () -> nil
134
+ def kill_with_timeout: (Numeric timeout) -> nil
135
+ def request_stop: () -> nil
136
+ def request_kill: () -> nil
137
+ def request_drain: () -> nil
138
+ def wait_until_stopped: () -> SandboxStopResult
124
139
  end
125
140
 
141
+ # Deprecated alias for SandboxHandle (was a read-only metadata type pre-v0.5.8).
142
+ SandboxInfo: singleton(SandboxHandle)
143
+
126
144
  class SandboxStopResult
127
145
  def name: () -> String
128
146
  def status: () -> Symbol
@@ -140,7 +158,8 @@ module Microsandbox
140
158
  ?user: String?, ?hostname: String?, ?labels: Hash[untyped, untyped]?,
141
159
  ?scripts: Hash[untyped, untyped]?, ?entrypoint: Array[String]?,
142
160
  ?ports: Hash[untyped, untyped]?, ?ports_udp: Hash[untyped, untyped]?,
143
- ?volumes: Hash[untyped, untyped]?, ?network: untyped?, ?from_snapshot: String?,
161
+ ?volumes: Hash[untyped, untyped]?, ?network: untyped?,
162
+ ?patches: Array[Hash[untyped, untyped]]?, ?from_snapshot: String?,
144
163
  ?log_level: (String | Symbol)?, ?quiet_logs: bool, ?security: (String | Symbol)?,
145
164
  ?oci_upper_size: Integer?, ?max_duration: Integer?, ?idle_timeout: Integer?,
146
165
  ?rlimits: Hash[untyped, untyped]?, ?pull_policy: (String | Symbol)?,
@@ -150,9 +169,9 @@ module Microsandbox
150
169
  ?replace: bool, ?replace_with_timeout: Numeric?)
151
170
  ?{ (Sandbox) -> untyped } -> untyped
152
171
  def self.start: (String name, ?detached: bool) -> Sandbox
153
- def self.get: (String name) -> SandboxInfo
154
- def self.list: () -> Array[SandboxInfo]
155
- def self.list_with: (?labels: Hash[untyped, untyped]) -> Array[SandboxInfo]
172
+ def self.get: (String name) -> SandboxHandle
173
+ def self.list: () -> Array[SandboxHandle]
174
+ def self.list_with: (?labels: Hash[untyped, untyped]) -> Array[SandboxHandle]
156
175
  def self.remove: (String name) -> nil
157
176
 
158
177
  def name: () -> String
@@ -162,23 +181,28 @@ module Microsandbox
162
181
  def shell: (String script, ?cwd: String?, ?user: String?, ?env: Hash[untyped, untyped]?,
163
182
  ?timeout: Numeric?, ?tty: bool, ?stdin: String?, ?rlimits: Hash[untyped, untyped]?) -> ExecOutput
164
183
  def exec_stream: (String command, ?Array[String] args, ?cwd: String?, ?user: String?,
165
- ?env: Hash[untyped, untyped]?, ?timeout: Numeric?, ?tty: bool, ?stdin: String?,
184
+ ?env: Hash[untyped, untyped]?, ?timeout: Numeric?, ?tty: bool, ?stdin: (String | :pipe)?,
166
185
  ?rlimits: Hash[untyped, untyped]?) -> ExecHandle
167
186
  def shell_stream: (String script, ?cwd: String?, ?user: String?, ?env: Hash[untyped, untyped]?,
168
- ?timeout: Numeric?, ?tty: bool, ?stdin: String?, ?rlimits: Hash[untyped, untyped]?) -> ExecHandle
187
+ ?timeout: Numeric?, ?tty: bool, ?stdin: (String | :pipe)?, ?rlimits: Hash[untyped, untyped]?) -> ExecHandle
188
+ def attach: (String command, ?Array[String] args, ?cwd: String?, ?user: String?,
189
+ ?env: Hash[untyped, untyped]?, ?detach_keys: String?,
190
+ ?rlimits: Hash[untyped, untyped]?) -> Integer
191
+ def attach_shell: () -> Integer
169
192
  def fs: () -> FS
193
+ def ssh: () -> SshOps
170
194
  def metrics: () -> Metrics
171
195
  def logs: (?tail: Integer?, ?since_ms: Numeric?, ?until_ms: Numeric?,
172
196
  ?sources: Array[String | Symbol]?) -> Array[LogEntry]
173
197
  def metrics_stream: (?interval: Numeric) -> MetricsStream
174
198
  def log_stream: (?sources: Array[String | Symbol]?, ?since_ms: Numeric?,
175
199
  ?from_cursor: String?, ?until_ms: Numeric?, ?follow: bool) -> LogStream
176
- def stop: (?timeout: Numeric?) -> nil
177
- def kill: (?timeout: Numeric?) -> nil
178
- def request_stop: () -> nil
179
- def request_kill: () -> nil
180
- def request_drain: () -> nil
181
- def wait_until_stopped: () -> SandboxStopResult
200
+ def stop: () -> nil
201
+ def stop_and_wait: () -> ExitStatus
202
+ def kill: () -> nil
203
+ def drain: () -> nil
204
+ def wait: () -> ExitStatus
205
+ def status: () -> Symbol
182
206
  def owns_lifecycle?: () -> bool
183
207
  def detach: () -> nil
184
208
  end
@@ -210,7 +234,7 @@ module Microsandbox
210
234
  end
211
235
 
212
236
  class ExitStatus
213
- def exit_code: () -> Integer
237
+ def exit_code: () -> Integer?
214
238
  def success?: () -> bool
215
239
  def failure?: () -> bool
216
240
  end
@@ -321,4 +345,130 @@ module Microsandbox
321
345
  ?with_image: bool, ?plain_tar: bool) -> nil
322
346
  def self.import: (String archive_path, ?dest: String?) -> SnapshotInfo
323
347
  end
348
+
349
+ module Patch
350
+ def self.text: (String path, String content, ?mode: Integer?, ?replace: bool) -> Hash[String, untyped]
351
+ def self.file: (String path, String content, ?mode: Integer?, ?replace: bool) -> Hash[String, untyped]
352
+ def self.append: (String path, String content) -> Hash[String, untyped]
353
+ def self.copy_file: (String src, String dst, ?mode: Integer?, ?replace: bool) -> Hash[String, untyped]
354
+ def self.copy_dir: (String src, String dst, ?replace: bool) -> Hash[String, untyped]
355
+ def self.symlink: (String target, String link, ?replace: bool) -> Hash[String, untyped]
356
+ def self.mkdir: (String path, ?mode: Integer?) -> Hash[String, untyped]
357
+ def self.remove: (String path) -> Hash[String, untyped]
358
+ end
359
+
360
+ module Destination
361
+ def self.any: () -> Hash[String, String]
362
+ def self.ip: (String value) -> Hash[String, String]
363
+ def self.cidr: (String value) -> Hash[String, String]
364
+ def self.domain: (String value) -> Hash[String, String]
365
+ def self.domain_suffix: (String value) -> Hash[String, String]
366
+ def self.group: ((String | Symbol) value) -> Hash[String, String]
367
+ end
368
+
369
+ module Rule
370
+ def self.allow: (?destination: untyped?, ?direction: (String | Symbol),
371
+ ?protocol: (String | Symbol)?, ?protocols: Array[String | Symbol]?,
372
+ ?port: (String | Integer)?, ?ports: Array[String | Integer]?) -> Hash[String, untyped]
373
+ def self.deny: (?destination: untyped?, ?direction: (String | Symbol),
374
+ ?protocol: (String | Symbol)?, ?protocols: Array[String | Symbol]?,
375
+ ?port: (String | Integer)?, ?ports: Array[String | Integer]?) -> Hash[String, untyped]
376
+ end
377
+
378
+ class NetworkPolicy
379
+ PRESET_ALIASES: Hash[String, String]
380
+ def self.public_only: () -> NetworkPolicy
381
+ def self.none: () -> NetworkPolicy
382
+ def self.allow_all: () -> NetworkPolicy
383
+ def self.non_local: () -> NetworkPolicy
384
+ def self.preset: ((String | Symbol) name) -> NetworkPolicy
385
+ def self.custom: (?default_egress: (String | Symbol)?, ?default_ingress: (String | Symbol)?,
386
+ ?rules: Array[Hash[untyped, untyped]], ?deny_domains: Array[String],
387
+ ?deny_domain_suffixes: Array[String]) -> NetworkPolicy
388
+ def self.coerce: (untyped network) -> Hash[String, untyped]
389
+ def initialize: (Hash[String, untyped] wire) -> void
390
+ def to_h: () -> Hash[String, untyped]
391
+ end
392
+
393
+ class AgentFrame
394
+ def initialize: (Hash[String, untyped] data) -> void
395
+ def id: () -> Integer
396
+ def flags: () -> Integer
397
+ def body: () -> String
398
+ def terminal?: () -> bool
399
+ def session_start?: () -> bool
400
+ def shutdown?: () -> bool
401
+ end
402
+
403
+ class AgentStream
404
+ include Enumerable[AgentFrame]
405
+ def id: () -> Integer
406
+ def recv: () -> AgentFrame?
407
+ def each: () { (AgentFrame) -> void } -> self
408
+ | () -> Enumerator[AgentFrame, self]
409
+ def close: () -> nil
410
+ end
411
+
412
+ class AgentClient
413
+ FLAG_TERMINAL: Integer
414
+ FLAG_SESSION_START: Integer
415
+ FLAG_SHUTDOWN: Integer
416
+ def self.connect_sandbox: (String name, ?timeout: Numeric?) ?{ (AgentClient) -> untyped } -> untyped
417
+ def self.connect_path: (String path, ?timeout: Numeric?) ?{ (AgentClient) -> untyped } -> untyped
418
+ def self.socket_path: (String name) -> String
419
+ def initialize: (untyped native) -> void
420
+ def request: (Integer flags, String body) -> AgentFrame
421
+ def stream: (Integer flags, String body) -> AgentStream
422
+ def send_frame: (Integer id, Integer flags, String body) -> nil
423
+ def ready_bytes: () -> String
424
+ def close: () -> nil
425
+ end
426
+
427
+ class SshOutput
428
+ def initialize: (Hash[String, untyped] data) -> void
429
+ def status: () -> Integer
430
+ def success?: () -> bool
431
+ def failure?: () -> bool
432
+ def stdout: () -> String
433
+ def stderr: () -> String
434
+ def stdout_bytes: () -> String
435
+ def stderr_bytes: () -> String
436
+ def to_s: () -> String
437
+ end
438
+
439
+ class SftpClient
440
+ def initialize: (untyped native) -> void
441
+ def read: (String path) -> String
442
+ def read_text: (String path) -> String
443
+ def write: (String path, String data) -> nil
444
+ def mkdir: (String path) -> nil
445
+ def remove_file: (String path) -> nil
446
+ def remove_dir: (String path) -> nil
447
+ def rename: (String old_path, String new_path) -> nil
448
+ def symlink: (String target, String link_path) -> nil
449
+ def real_path: (String path) -> String
450
+ def read_link: (String path) -> String
451
+ def close: () -> nil
452
+ end
453
+
454
+ class SshClient
455
+ def initialize: (untyped native) -> void
456
+ def exec: (String command, ?tty: bool) -> SshOutput
457
+ def attach: (?term: String?, ?detach_keys: String?) -> Integer
458
+ def sftp: () ?{ (SftpClient) -> untyped } -> untyped
459
+ def close: () -> nil
460
+ end
461
+
462
+ class SshServer
463
+ def initialize: (untyped native) -> void
464
+ def serve_connection: () -> nil
465
+ def close: () -> nil
466
+ end
467
+
468
+ class SshOps
469
+ def initialize: (untyped native) -> void
470
+ def open_client: (?user: String, ?term: String?, ?sftp: bool) ?{ (SshClient) -> untyped } -> untyped
471
+ def prepare_server: (?host_key_path: String?, ?authorized_keys_path: String?,
472
+ ?user: String?, ?sftp: bool) -> SshServer
473
+ end
324
474
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: microsandbox-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.8
4
+ version: 0.5.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - ya-luotao
@@ -45,6 +45,8 @@ files:
45
45
  - README.md
46
46
  - ext/microsandbox/Cargo.toml
47
47
  - ext/microsandbox/extconf.rb
48
+ - ext/microsandbox/src/agent.rs
49
+ - ext/microsandbox/src/backend.rs
48
50
  - ext/microsandbox/src/conv.rs
49
51
  - ext/microsandbox/src/error.rs
50
52
  - ext/microsandbox/src/exec.rs
@@ -53,9 +55,11 @@ files:
53
55
  - ext/microsandbox/src/runtime.rs
54
56
  - ext/microsandbox/src/sandbox.rs
55
57
  - ext/microsandbox/src/snapshot.rs
58
+ - ext/microsandbox/src/ssh.rs
56
59
  - ext/microsandbox/src/stream.rs
57
60
  - ext/microsandbox/src/volume.rs
58
61
  - lib/microsandbox.rb
62
+ - lib/microsandbox/agent.rb
59
63
  - lib/microsandbox/errors.rb
60
64
  - lib/microsandbox/exec_handle.rb
61
65
  - lib/microsandbox/exec_output.rb
@@ -63,8 +67,11 @@ files:
63
67
  - lib/microsandbox/image.rb
64
68
  - lib/microsandbox/log_entry.rb
65
69
  - lib/microsandbox/metrics.rb
70
+ - lib/microsandbox/network.rb
71
+ - lib/microsandbox/patch.rb
66
72
  - lib/microsandbox/sandbox.rb
67
73
  - lib/microsandbox/snapshot.rb
74
+ - lib/microsandbox/ssh.rb
68
75
  - lib/microsandbox/streams.rb
69
76
  - lib/microsandbox/version.rb
70
77
  - lib/microsandbox/volume.rb