Class: Boxd::Box
- Inherits:
-
Object
- Object
- Boxd::Box
- Defined in:
- lib/boxd/box.rb
Overview
A Box is the handle to a single VM. Instances are returned from Compute#boxes operations; you don’t construct them directly.
Instance Attribute Summary collapse
-
#image ⇒ Object
readonly
Returns the value of attribute image.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#status ⇒ Object
readonly
Returns the value of attribute status.
-
#url ⇒ Object
readonly
Returns the value of attribute url.
-
#vm_id ⇒ Object
readonly
Returns the value of attribute vm_id.
Instance Method Summary collapse
- #destroy ⇒ Object
-
#exec(cmd, env: nil, tty: false, timeout: nil, raise_on_error: false, &block) ⇒ Object
Run a command inside the VM.
-
#exec!(cmd, **opts) ⇒ Object
Run a command and return stdout as a String, raising on any non-zero exit.
-
#initialize(attrs, backend:) ⇒ Box
constructor
A new instance of Box.
- #inspect ⇒ Object
-
#read_file(remote_path, local_path = nil) ⇒ Object
Copy a file FROM the VM to the local filesystem.
- #reboot ⇒ Object
-
#refresh! ⇒ Object
Fetch the latest state from the API and update this Box in place.
- #resume ⇒ Object
- #running? ⇒ Boolean
- #suspend ⇒ Object (also: #pause)
- #suspended? ⇒ Boolean
-
#to_h ⇒ Object
Convenience: hash representation of the current cached state.
-
#wait_for(target, timeout: 60, interval: 1) ⇒ Object
Wait until status matches ‘target` (String or Array).
-
#write_file(path, content) ⇒ Object
Write content to a path inside the VM.
Constructor Details
#initialize(attrs, backend:) ⇒ Box
Returns a new instance of Box.
11 12 13 14 |
# File 'lib/boxd/box.rb', line 11 def initialize(attrs, backend:) @backend = backend refresh_from(attrs) end |
Instance Attribute Details
#image ⇒ Object (readonly)
Returns the value of attribute image.
9 10 11 |
# File 'lib/boxd/box.rb', line 9 def image @image end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
9 10 11 |
# File 'lib/boxd/box.rb', line 9 def name @name end |
#status ⇒ Object (readonly)
Returns the value of attribute status.
9 10 11 |
# File 'lib/boxd/box.rb', line 9 def status @status end |
#url ⇒ Object (readonly)
Returns the value of attribute url.
9 10 11 |
# File 'lib/boxd/box.rb', line 9 def url @url end |
#vm_id ⇒ Object (readonly)
Returns the value of attribute vm_id.
9 10 11 |
# File 'lib/boxd/box.rb', line 9 def vm_id @vm_id end |
Instance Method Details
#destroy ⇒ Object
120 121 122 123 124 |
# File 'lib/boxd/box.rb', line 120 def destroy @backend.call_raw("destroy", @name, "--confirm") @status = "destroyed" self end |
#exec(cmd, env: nil, tty: false, timeout: nil, raise_on_error: false, &block) ⇒ Object
Run a command inside the VM.
box.exec(["ls", "-la"]) # sync, blocking
box.exec(["sleep", "3"], timeout: 1) # raises TimeoutError
box.exec(["bash", "-lc", "for i in 1 2 3; ...]) do |stream, chunk|
# stream is :stdout or :stderr
end
Returns Hash stderr:, exit_code:. Raises ExecError if ‘raise_on_error: true` and exit_code != 0.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/boxd/box.rb', line 51 def exec(cmd, env: nil, tty: false, timeout: nil, raise_on_error: false, &block) result = if timeout run_with_timeout(timeout) { @backend.exec_stream(@name, cmd, env: env, tty: tty, &block) } else @backend.exec_stream(@name, cmd, env: env, tty: tty, &block) end if raise_on_error && result[:exit_code] != 0 raise ExecError.new( "exec exited #{result[:exit_code]}: #{result[:stderr].strip.lines.last}", **result, ) end result end |
#exec!(cmd, **opts) ⇒ Object
Run a command and return stdout as a String, raising on any non-zero exit. Convenience for one-liners.
70 71 72 73 |
# File 'lib/boxd/box.rb', line 70 def exec!(cmd, **opts) r = exec(cmd, **opts, raise_on_error: true) r[:stdout] end |
#inspect ⇒ Object
139 140 141 |
# File 'lib/boxd/box.rb', line 139 def inspect "#<Boxd::Box name=#{@name.inspect} status=#{@status.inspect} url=#{@url.inspect}>" end |
#read_file(remote_path, local_path = nil) ⇒ Object
Copy a file FROM the VM to the local filesystem. Returns the local path.
98 99 100 101 102 |
# File 'lib/boxd/box.rb', line 98 def read_file(remote_path, local_path = nil) local_path ||= Tempfile.new(File.basename(remote_path)).path @backend.call_raw("cp", "#{@name}:#{remote_path}", local_path) local_path end |
#reboot ⇒ Object
115 116 117 118 |
# File 'lib/boxd/box.rb', line 115 def reboot @backend.call_raw("reboot", @name) refresh! end |
#refresh! ⇒ Object
Fetch the latest state from the API and update this Box in place.
17 18 19 20 |
# File 'lib/boxd/box.rb', line 17 def refresh! refresh_from(@backend.call_json("info", @name)) self end |
#resume ⇒ Object
110 111 112 113 |
# File 'lib/boxd/box.rb', line 110 def resume @backend.call_raw("resume", @name) refresh! end |
#running? ⇒ Boolean
33 34 35 |
# File 'lib/boxd/box.rb', line 33 def running? status == "running" end |
#suspend ⇒ Object Also known as: pause
104 105 106 107 |
# File 'lib/boxd/box.rb', line 104 def suspend @backend.call_raw("pause", @name) refresh! end |
#suspended? ⇒ Boolean
37 38 39 |
# File 'lib/boxd/box.rb', line 37 def suspended? %w[hibernated standby paused].include?(status) end |
#to_h ⇒ Object
Convenience: hash representation of the current cached state.
23 24 25 26 27 28 29 30 31 |
# File 'lib/boxd/box.rb', line 23 def to_h { name: @name, vm_id: @vm_id, url: @url, status: @status, image: @image, } end |
#wait_for(target, timeout: 60, interval: 1) ⇒ Object
Wait until status matches ‘target` (String or Array). Polls `info`. Returns self on match; raises TimeoutError after `timeout` seconds.
128 129 130 131 132 133 134 135 136 137 |
# File 'lib/boxd/box.rb', line 128 def wait_for(target, timeout: 60, interval: 1) targets = Array(target).map(&:to_s) deadline = Time.now + timeout until targets.include?(refresh!.status) raise TimeoutError, "wait_for(#{targets.inspect}) timed out after #{timeout}s; status=#{status}" \ if Time.now >= deadline sleep interval end self end |
#write_file(path, content) ⇒ Object
Write content to a path inside the VM.
box.write_file("/tmp/hello.txt", "hello world")
box.write_file("/etc/conf", File.read("./conf"))
box.write_file("/tmp/blob", io_object) # responds to :read
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/boxd/box.rb', line 80 def write_file(path, content) data = if content.respond_to?(:read) content.read else content.to_s end Tempfile.create(["boxd-write", File.extname(path)]) do |tmp| tmp.binmode tmp.write(data) tmp.flush @backend.call_raw("cp", tmp.path, "#{@name}:#{path}") end path end |