Module: Microsandbox::Patch

Defined in:
lib/microsandbox/patch.rb

Overview

Factory for **rootfs patches** — modifications applied to a sandbox’s root filesystem before the microVM boots. Pass them to Sandbox.create via the ‘patches:` keyword:

Patches apply to OverlayFS (OCI) and bind rootfs; they are not compatible with disk-image roots. Each factory returns a plain Hash, so a patch list is just an Array of Hashes — you may also build them by hand. Mirrors the ‘Patch` factory in the official Python/Node/Go SDKs.

Examples:

Microsandbox::Sandbox.create("box", image: "alpine",
  patches: [
    Microsandbox::Patch.text("/etc/app.conf", "key = value\n", mode: 0o644),
    Microsandbox::Patch.mkdir("/opt/app"),
    Microsandbox::Patch.copy_file("./cert.pem", "/etc/ssl/app.pem"),
    Microsandbox::Patch.symlink("/etc/app.conf", "/etc/app.link"),
    Microsandbox::Patch.remove("/etc/motd"),
  ]) do |sb|
  # ...
end

Class Method Summary collapse

Class Method Details

.append(path, content) ⇒ Hash

Append text to an existing file. For OCI roots, a file living only in a lower image layer is copied up first, then appended.

Returns:

  • (Hash)


54
55
56
# File 'lib/microsandbox/patch.rb', line 54

def append(path, content)
  { "kind" => "append", "path" => path.to_s, "content" => content.to_s }
end

.copy_dir(src, dst, replace: false) ⇒ Hash

Copy a host directory (recursively) into the rootfs.

Returns:

  • (Hash)


72
73
74
# File 'lib/microsandbox/patch.rb', line 72

def copy_dir(src, dst, replace: false)
  { "kind" => "copy_dir", "src" => src.to_s, "dst" => dst.to_s, "replace" => replace ? true : false }
end

.copy_file(src, dst, mode: nil, replace: false) ⇒ Hash

Copy a host file into the rootfs.

Parameters:

  • src (String)

    host path

  • dst (String)

    absolute guest destination

  • mode (Integer, nil) (defaults to: nil)

    file mode (preserves source mode when nil)

  • replace (Boolean) (defaults to: false)

Returns:

  • (Hash)


64
65
66
67
68
# File 'lib/microsandbox/patch.rb', line 64

def copy_file(src, dst, mode: nil, replace: false)
  h = { "kind" => "copy_file", "src" => src.to_s, "dst" => dst.to_s, "replace" => replace ? true : false }
  h["mode"] = Integer(mode) unless mode.nil?
  h
end

.file(path, content, mode: nil, replace: false) ⇒ Hash

Write raw bytes to a file (binary-safe; content may contain NUL).

Parameters:

  • path (String)

    absolute guest path

  • content (String)

    raw bytes to write

  • mode (Integer, nil) (defaults to: nil)

    file mode

  • replace (Boolean) (defaults to: false)

Returns:

  • (Hash)


45
46
47
48
49
# File 'lib/microsandbox/patch.rb', line 45

def file(path, content, mode: nil, replace: false)
  h = { "kind" => "file", "path" => path.to_s, "content" => content.to_s, "replace" => replace ? true : false }
  h["mode"] = Integer(mode) unless mode.nil?
  h
end

.mkdir(path, mode: nil) ⇒ Hash

Create a directory (idempotent — no error if it already exists).

Parameters:

  • path (String)

    absolute guest path

  • mode (Integer, nil) (defaults to: nil)

    directory mode (e.g. 0o755)

Returns:

  • (Hash)


86
87
88
89
90
# File 'lib/microsandbox/patch.rb', line 86

def mkdir(path, mode: nil)
  h = { "kind" => "mkdir", "path" => path.to_s }
  h["mode"] = Integer(mode) unless mode.nil?
  h
end

.remove(path) ⇒ Hash

Remove a file or directory (idempotent — no error if absent).

Returns:

  • (Hash)


94
95
96
# File 'lib/microsandbox/patch.rb', line 94

def remove(path)
  { "kind" => "remove", "path" => path.to_s }
end

Create a symlink at link pointing to target.

Returns:

  • (Hash)


78
79
80
# File 'lib/microsandbox/patch.rb', line 78

def symlink(target, link, replace: false)
  { "kind" => "symlink", "target" => target.to_s, "link" => link.to_s, "replace" => replace ? true : false }
end

.text(path, content, mode: nil, replace: false) ⇒ Hash

Write UTF-8 text to a file, creating it (or replacing it when replace).

Parameters:

  • path (String)

    absolute guest path

  • content (String)

    text to write

  • mode (Integer, nil) (defaults to: nil)

    file mode (e.g. 0o644)

  • replace (Boolean) (defaults to: false)

    allow shadowing a path already in the rootfs

Returns:

  • (Hash)


33
34
35
36
37
# File 'lib/microsandbox/patch.rb', line 33

def text(path, content, mode: nil, replace: false)
  h = { "kind" => "text", "path" => path.to_s, "content" => content.to_s, "replace" => replace ? true : false }
  h["mode"] = Integer(mode) unless mode.nil?
  h
end