Class: Kitchen::Transport::Rsync::Connection

Inherits:
Ssh::Connection
  • Object
show all
Defined in:
lib/kitchen/transport/rsync.rb

Instance Method Summary collapse

Instance Method Details

#copy_identity ⇒ Object

Copy your SSH identity, creating a new one if needed



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/kitchen/transport/rsync.rb', line 75

def copy_identity
  return if @copied_identity
  identities = Net::SSH::Authentication::Agent.connect.identities
  raise 'No SSH identities found. Please run ssh-add.' if identities.empty?
  key = identities.first
  enc_key = Base64.encode64(key.to_blob).gsub("\n", '')
  identitiy = "ssh-rsa #{enc_key} #{key.comment}"
  @session.exec! <<-EOT
    test -e ~/.ssh || mkdir ~/.ssh
    test -e ~/.ssh/authorized_keys || touch ~/.ssh/authorized_keys
    if ! grep -q "#{identitiy}" ~/.ssh/authorized_keys ; then
      chmod go-w ~ ~/.ssh ~/.ssh/authorized_keys ; \
      echo "#{identitiy}" >> ~/.ssh/authorized_keys
    fi
  EOT
  @copied_identity = true
end

#ssh_args ⇒ Object



93
94
95
96
97
98
99
100
101
# File 'lib/kitchen/transport/rsync.rb', line 93

def ssh_args
  args = %W{ -o UserKnownHostsFile=/dev/null }
  args += %W{ -o StrictHostKeyChecking=no }
  args += %W{ -o IdentitiesOnly=yes } if @options[:keys]
  args += %W{ -o LogLevel=#{@logger.debug? ? "VERBOSE" : "ERROR"} }
  args += %W{ -o ForwardAgent=#{options[:forward_agent] ? "yes" : "no"} } if @options.key? :forward_agent
  Array(@options[:keys]).each { |ssh_key| args += %W{ -i #{ssh_key}} }
  args += %W{ -p #{@session.options[:port]}}
end

#upload(locals, remote) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/kitchen/transport/rsync.rb', line 41

def upload(locals, remote)
  if @rsync_failed || !File.exists?('/usr/bin/rsync')
    logger.debug('[rsync] Rsync already failed or not installed, not trying it')
    return super
  end

  locals = Array(locals)
  # We only try to sync folders for now.
  rsync_candidates = locals.select {|path| File.directory?(path) }
  ssh_command = "ssh #{ssh_args.join(' ')}"
  copy_identity
  rsync_cmd = "/usr/bin/rsync -e '#{ssh_command}' -az#{logger.level == :debug ? 'vv' : ''} #{rsync_candidates.join(' ')} #{@session.options[:user]}@#{@session.host}:#{remote}"
  logger.debug("[rsync] Running rsync command: #{rsync_cmd}")
  ret = []
  time = Benchmark.realtime do
    ret << system(rsync_cmd)
  end
  logger.info("[rsync] Time taken to upload #{rsync_candidates.join(';')} to #{self}:#{remote}: %.2f sec" % time)
  unless ret.first
    logger.warn("[rsync] rsync exited with status #{$?.exitstatus}, using SCP instead")
    @rsync_failed = true
  end

  # Fall back to SCP
  remaining = if @rsync_failed
    locals
  else
    locals - rsync_candidates
  end
  logger.debug("[rsync] Using fallback to upload #{remaining.join(';')}")
  super(remaining, remote) unless remaining.empty?
end