Class: Sprites::Resources::Exec

Inherits:
Object
  • Object
show all
Defined in:
lib/sprites/resources/exec.rb

Overview

Command execution on sprites via HTTP and WebSocket.

Defined Under Namespace

Classes: Result, Session

Constant Summary collapse

STREAM_STDIN =
0
STREAM_STDOUT =
1
STREAM_STDERR =
2
STREAM_EXIT =
3
STREAM_STDIN_EOF =
4

Instance Method Summary collapse

Constructor Details

#initialize(client) ⇒ Exec



20
21
22
# File 'lib/sprites/resources/exec.rb', line 20

def initialize(client)
  @client = client
end

Instance Method Details

#attach(sprite_name, session_id, input: $stdin, output: $stdout) ⇒ Object

Attach to an existing exec session.



80
81
82
83
84
# File 'lib/sprites/resources/exec.rb', line 80

def attach(sprite_name, session_id, input: $stdin, output: $stdout)
  run_interactive(input: input, output: output) do |block|
    connect(sprite_name, session_id: session_id, tty: true, &block)
  end
end

#connect(sprite_name, command: nil, tty: false, **options) {|Async::Task, Session| ... } ⇒ Object

Connect to a WebSocket exec session.

Yields the Async task and session for concurrent I/O.

Examples:

client.exec.connect(sprite.name, command: ["bash"], tty: true) do |task, session|
  session.on_stdout { |data| print data }
  task.async do
    while (line = $stdin.gets)
      session.write(line)
    end
  end
end

Yields:

  • (Async::Task, Session)

    task and session for callbacks



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/sprites/resources/exec.rb', line 120

def connect(sprite_name, command: nil, tty: false, **options, &block)
  url = build_websocket_url(sprite_name, command, tty: tty, **options)
  endpoint = Async::HTTP::Endpoint.parse(url, alpn_protocols: ["http/1.1"])
  headers = Protocol::HTTP::Headers.new
  headers["authorization"] = "Bearer #{@client.token}"

  Async do |task|
    Async::WebSocket::Client.connect(endpoint, headers: headers) do |connection|
      session = Session.new(connection, tty: tty)

      # Run user's block and read loop concurrently
      task.async { block.call(task, session) }
      session.read_loop
    end
  end
end

#create(sprite_name, command:) ⇒ Hash

Execute a command via HTTP POST (non-streaming).



29
30
31
# File 'lib/sprites/resources/exec.rb', line 29

def create(sprite_name, command:)
  @client.post("/v1/sprites/#{sprite_name}/exec", { command: })
end

#interactive(sprite_name, command, input: $stdin, output: $stdout, **options) ⇒ Object

Start an interactive terminal session wired to stdin/stdout.



68
69
70
71
72
# File 'lib/sprites/resources/exec.rb', line 68

def interactive(sprite_name, command, input: $stdin, output: $stdout, **options)
  run_interactive(input: input, output: output) do |block|
    connect(sprite_name, command: command, tty: true, **options, &block)
  end
end

#kill(sprite_name, session_id, signal: nil, timeout: nil) {|Hash| ... } ⇒ Array<Hash>

Kill an exec session.

Yields:

  • (Hash)

    streaming NDJSON events (signal, exited, complete)



94
95
96
97
98
99
# File 'lib/sprites/resources/exec.rb', line 94

def kill(sprite_name, session_id, signal: nil, timeout: nil, &block)
  body = {}
  body[:signal] = signal if signal
  body[:timeout] = timeout if timeout
  @client.post_stream("/v1/sprites/#{sprite_name}/exec/#{session_id}/kill", body, &block)
end

#list(sprite_name) ⇒ Array<Hash>

List active exec sessions.



37
38
39
# File 'lib/sprites/resources/exec.rb', line 37

def list(sprite_name)
  @client.get("/v1/sprites/#{sprite_name}/exec")
end

#run(sprite_name, command, **options) ⇒ Result

Run a command via WebSocket and return the result (blocking).



47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/sprites/resources/exec.rb', line 47

def run(sprite_name, command, **options)
  stdout = +""
  stderr = +""
  exit_code = nil

  connect(sprite_name, command: command, **options) do |_task, session|
    session.on_stdout { |data| stdout << data }
    session.on_stderr { |data| stderr << data }
    session.on_exit { |code| exit_code = code }
  end

  Result.new(stdout: stdout, stderr: stderr, exit_code: exit_code)
end