Class: Kdeploy::Executor

Inherits:
Object
  • Object
show all
Defined in:
lib/kdeploy/executor.rb

Overview

SSH/SCP executor for remote command execution and file operations

Instance Method Summary collapse

Constructor Details

#initialize(host_config) ⇒ Executor

Returns a new instance of Executor.



10
11
12
13
14
15
16
17
18
19
20
# File 'lib/kdeploy/executor.rb', line 10

def initialize(host_config)
  @host = host_config[:name]
  @user = host_config[:user]
  @ip = host_config[:ip]
  @password = host_config[:password]
  @key = host_config[:key]
  @port = host_config[:port] # 新增端口支持
  @use_sudo = host_config[:use_sudo] || false
  @sudo_password = host_config[:sudo_password]
  @base_dir = host_config[:base_dir] # Base directory for resolving relative paths
end

Instance Method Details

#build_command_result(stdout, stderr, command) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/kdeploy/executor.rb', line 60

def build_command_result(stdout, stderr, command)
  {
    stdout: stdout.strip,
    stderr: stderr.strip,
    command: command
  }
end

#execute(command, use_sudo: nil) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/kdeploy/executor.rb', line 22

def execute(command, use_sudo: nil)
  use_sudo = @use_sudo if use_sudo.nil?
  command = wrap_with_sudo(command) if use_sudo

  Net::SSH.start(@ip, @user, ssh_options) do |ssh|
    execute_command_on_ssh(ssh, command)
  end
rescue Net::SSH::AuthenticationFailed => e
  raise SSHError.new("SSH authentication failed: #{e.message}", e)
rescue StandardError => e
  raise SSHError.new("SSH execution failed: #{e.message}", e)
end

#execute_command_on_ssh(ssh, command) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/kdeploy/executor.rb', line 35

def execute_command_on_ssh(ssh, command)
  stdout = String.new
  stderr = String.new

  ssh.open_channel do |channel|
    channel.exec(command) do |_ch, success|
      raise SSHError, "Could not execute command: #{command}" unless success

      setup_channel_handlers(channel, stdout, stderr)
    end
  end
  ssh.loop
  build_command_result(stdout, stderr, command)
end

#setup_channel_handlers(channel, stdout, stderr) ⇒ Object



50
51
52
53
54
55
56
57
58
# File 'lib/kdeploy/executor.rb', line 50

def setup_channel_handlers(channel, stdout, stderr)
  channel.on_data do |_ch, data|
    stdout << data
  end

  channel.on_extended_data do |_ch, _type, data|
    stderr << data
  end
end

#upload(source, destination, use_sudo: nil) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/kdeploy/executor.rb', line 68

def upload(source, destination, use_sudo: nil)
  use_sudo = @use_sudo if use_sudo.nil?

  # Resolve relative paths relative to base_dir
  resolved_source = resolve_path(source)

  # If destination requires sudo, upload to temp location first, then move with sudo
  if use_sudo || requires_sudo?(destination)
    upload_with_sudo(resolved_source, destination)
  else
    Net::SCP.start(@ip, @user, ssh_options) do |scp|
      scp.upload!(resolved_source, destination)
    end
  end
rescue StandardError => e
  raise SCPError.new("SCP upload failed: #{e.message}", e)
end

#upload_template(source, destination, variables = {}) ⇒ Object



86
87
88
89
90
91
92
# File 'lib/kdeploy/executor.rb', line 86

def upload_template(source, destination, variables = {})
  # Resolve relative paths relative to base_dir
  resolved_source = resolve_path(source)
  Template.render_and_upload(self, resolved_source, destination, variables)
rescue StandardError => e
  raise TemplateError.new("Template upload failed: #{e.message}", e)
end