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



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/kitchen/transport/rsync.rb', line 86

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! "    test -e ~/.ssh || mkdir ~/.ssh\n    test -e ~/.ssh/authorized_keys || touch ~/.ssh/authorized_keys\n    if ! grep -q \"\#{identitiy}\" ~/.ssh/authorized_keys ; then\n      chmod go-w ~ ~/.ssh ~/.ssh/authorized_keys ; \\\n      echo \"\#{identitiy}\" >> ~/.ssh/authorized_keys\n    fi\n  EOT\n  @copied_identity = true\nend\n"

#ssh_argsObject



104
105
106
107
108
109
110
111
112
# File 'lib/kitchen/transport/rsync.rb', line 104

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



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/kitchen/transport/rsync.rb', line 51

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