Module: K8s::ResourceClient::Exec::InstanceMethods

Defined in:
lib/k8s/resource_client/exec.rb

Instance Method Summary collapse

Instance Method Details

#exec(name:, namespace: @namespace, command:, container:, stdin: true, stdout: true, tty: true) {|String| ... } ⇒ String?

Executes arbitrary commands in a container.

Examples:

client.api('v1').resource('pods', namespace: 'default').exec(
  name: 'test-pod',
  container: 'shell',
  command: '/bin/sh'
)

Open a shell:

exec(name: 'my-pod', container: 'my-container', command: '/bin/sh')

Execute single command:

exec(name: 'my-pod', container: 'my-container', command: 'date')

Pass multiple arguments:

exec(name: 'my-pod', container: 'my-container', command: ['ls', '-la'])

Yield the output of the command:

exec(
  name: "test-pod",
  container: "shell",
  command: [ "watch", "date" ],
) do |out|
  puts "local time #{Time.now}"
  puts "server time #{out}"
end

Parameters:

  • name (String)

    name of the pod

  • namespace (String) (defaults to: @namespace)
  • container (String)

    name of the container to execute the command in

  • command (Array<String>|String)

    command to execute. It accepts a single string or an array of strings if multiple arguments are needed.

  • stdin (Boolean) (defaults to: true)

    whether to stream stdin to the container

  • stdout (Boolean) (defaults to: true)

    whether to stream stdout from the container

  • tty (Boolean) (defaults to: true)

    whether to allocate a tty for the container

Yields:

  • (String)

    Optional block to yield the output of the command

Returns:

  • (String, nil)

    output of the command. It returns nil if a block is given or tty is true.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/k8s/resource_client/exec.rb', line 50

def exec(name:, namespace: @namespace, command:, container:, stdin: true, stdout: true, tty: true)
  query = {
    command: [command].flatten,
    container: container,
    stdin: !!stdin,
    stdout: !!stdout,
    tty: !!tty
  }

  exec_path = path(name, namespace: namespace, subresource: "exec")
  output = StringIO.new

  EM.run do
    ws = @transport.build_ws_conn(exec_path, query)

    ws.on :message do |event|
      out = event.data.pack("C*")

      if block_given?
        yield(out)
      elsif tty
        print out
      else
        output.write(out)
      end
    end

    ws.on :error do |event|
      logger.error(event.message)
    end

    term_attributes_original = Termios.tcgetattr($stdin)
    if tty
      term_attributes = term_attributes_original.dup
      term_attributes.lflag &= ~Termios::ECHO
      term_attributes.lflag &= ~Termios::ICANON
      Termios.tcsetattr($stdin, Termios::TCSANOW, term_attributes)

      EM.open_keyboard(Module.new do
        define_method(:receive_data) do |input|
          input = [0] + input.unpack("C*")
          ws.send(input)
        end
      end)
    end

    ws.on :close do
      Termios.tcsetattr($stdin, Termios::TCSANOW, term_attributes_original)
      EM.stop
    end
  end

  return if tty

  output.rewind
  output.read
end