Sha256: 48b8922c434faadc4ade9ecab8633f29be2f5c7cd6a7a52e598defbc9b4fc2fa

Contents?: true

Size: 1.56 KB

Versions: 5

Compression:

Stored size: 1.56 KB

Contents

# frozen_string_literal: true

require 'forwardable'

class Kubectl
  ##
  # Handles running kubectl exec
  class Exec
    extend Forwardable

    def_delegators :@kubectl, :kubectl_base_command

    def initialize(kubectl)
      @kubectl = kubectl
    end

    def exec(pod:, command:)
      old_state = `stty -g`

      PTY.spawn("#{kubectl_base_command('exec', resource: pod)} #{command}") do |out, inp, pid|
        pty_process(out, inp, pid, old_state)
      end
    end

    private

    attr_reader :stdin_thread, :stdout_thread

    def prepare_stdin_thread(inp)
      @stdin_thread = Thread.new do
        until inp.closed?
          input = $stdin.getch
          inp.write(input)
          inp.flush
        end
      end
    end

    def prepare_stdout_thread(out)
      @stdout_thread = Thread.new do
        until out.eof?
          $stdout.print(out.readchar)
          $stdout.flush
        end
      rescue Errno::EIO, EOFError
        nil
      end
    end

    def pty_process(out, inp, pid, old_state)
      prepare_stdin_thread(inp)
      prepare_stdout_thread(out)

      stdin_thread.run

      wait_for_process(pid)

      stdout_thread.join
      stdin_thread.kill

      sleep 0.1
    ensure
      cleanup_pty(old_state)
    end

    def wait_for_process(pid)
      Process.waitpid(pid)
    rescue StandardError
      nil # "rescue nil" is there in case process already ended.
    end

    def cleanup_pty(old_stty_state)
      stdout_thread&.kill
      stdin_thread&.kill
      $stdout.puts
      $stdout.flush

      system("stty #{old_stty_state}")
    end
  end
end

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
kuberun-0.2.1 lib/kuberun/kubectl/exec.rb
kuberun-0.2.0 lib/kuberun/kubectl/exec.rb
kuberun-0.1.4 lib/kuberun/kubectl/exec.rb
kuberun-0.1.2 lib/kuberun/kubectl/exec.rb
kuberun-0.1.1 lib/kuberun/kubectl/exec.rb