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_identityObject

Copy your SSH identity, creating a new one if needed



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

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_argsObject



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

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
73
# 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 and ignore the cache folder
  # because we don't want to --delete that.
  rsync_candidates = locals.select {|path| File.directory?(path) && File.basename(path) != 'cache' }
  ssh_command = "ssh #{ssh_args.join(' ')}"
  copy_identity
  rsync_cmd = "/usr/bin/rsync -e '#{ssh_command}' -az#{logger.level == :debug ? 'vv' : ''} --delete #{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