Class: Rancher::Shell::CLI

Inherits:
Object
  • Object
show all
Includes:
LoggerHelper
Defined in:
lib/rancher/shell/cli.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from LoggerHelper

#exit_with_error, #logger

Constructor Details

#initializeCLI

Returns a new instance of CLI.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rancher/shell/cli.rb', line 21

def initialize
  @config_file_paths = [
    "#{ENV['HOME']}/.rancher-shell.yml",
    "#{Dir.pwd}/.rancher-shell.yml",
  ]
  @config = {}
  @config_file_paths.each do |file_path|
    if File.exists? file_path
      logger.debug "loading config from #{file_path}"
      config = YAML.load_file(file_path)
      logger.debug "  #{config}"
      @config.merge! config
    end
  end
  @projects = @config['projects']
  @project = @config['projects'].find { |project| project['id'] === @config['project'] } || @config['projects'].first
  logger.info "environment = #{@project['id']} - #{@project['name']}"
  logger.debug "  #{@project}"
  exit_with_error "API Host Required" unless @project['api'] && @project['api']['host']
  exit_with_error "API Key Required" unless @project['api'] && @project['api']['key']
  exit_with_error "API Secret Required" unless @project['api'] && @project['api']['secret']
end

Instance Attribute Details

#apiObject (readonly)

Returns the value of attribute api.



19
20
21
# File 'lib/rancher/shell/cli.rb', line 19

def api
  @api
end

#websocketObject (readonly)

Returns the value of attribute websocket.



19
20
21
# File 'lib/rancher/shell/cli.rb', line 19

def websocket
  @websocket
end

Class Method Details

.startObject



11
12
13
14
15
16
17
# File 'lib/rancher/shell/cli.rb', line 11

def self.start
  instance = self.new
  instance.setup_api!
  instance.retrieve_containers!
  instance.setup_websocket!
  instance.listen!
end

Instance Method Details

#listen!Object



44
45
46
47
48
49
50
51
52
# File 'lib/rancher/shell/cli.rb', line 44

def listen!
  $stdin.each_line do |command|
    if command.strip === 'exit'
      logger.info "connection closed"
      Kernel.exit true
    end
    @websocket.send Base64.encode64 command
  end
end

#retrieve_containers!Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/rancher/shell/cli.rb', line 62

def retrieve_containers!
  @response = @api.get(
    "containers",
  )
  @containers = @response.json['data'].map do |container|
    {
      'id' => container['id'],
      'name' => container['name'],
      'state' => container['state'],
      'ports' => container['ports'],
    }
  end
  @container = @containers.find { |container| container['name'] === @project['container'] }
  exit_with_error "could not find container: #{@project['container']}" unless @container
end

#setup_api!Object



54
55
56
57
58
59
60
# File 'lib/rancher/shell/cli.rb', line 54

def setup_api!
  @api = Rancher::Shell::Api.new(
    host: @project['api']['host'],
    user: @project['api']['key'],
    pass: @project['api']['secret'],
  )
end

#setup_websocket!Object



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
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/rancher/shell/cli.rb', line 78

def setup_websocket!
  logger.info "container = #{@container['id']}"
  @response = @api.post(
    "containers/#{@container['id']}?action=execute",
    "command" => [
      "/bin/sh",
      "-c",
      "TERM=xterm-256color; export TERM; [ -x /bin/bash ] && ([ -x /usr/bin/script ] && /usr/bin/script -q -c \"/bin/bash\" /dev/null || exec /bin/bash) || exec /bin/sh",
    ],
    "attachStdin" => true,
    "attachStdout" => true,
    "tty" => false,
  )
  websocket_url = "#{@response.json['url']}?token=#{@response.json['token']}"
  logger.info "connecting to #{@response.json['url']} ..."
  @websocket = Rancher::Shell::WebsocketClient.new websocket_url, headers: { 'Authorization' => "Bearer #{@response.json['token']}"}
  @websocket.on :open do |event|
    logger.info "  connected!"
  end
  @websocket.on :chunk do |encoded_chunk|
    chunk = Base64.decode64 encoded_chunk
    @buffer ||= ''
    @buffer << chunk if chunk
    if chunk.ord === 32
      emit :message, @buffer
      @buffer = ''
    end
  end
  @websocket.on :message do |data|
    $stdout.print data
  end
  @websocket.on :error do |event|
    logger.error "socket error: #{event}"
    Kernel.exit true
  end
  @websocket.on :close do
    logger.error "closed connection"
    Kernel.exit true
  end
end