2022-04-06 19:39:56 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
# Sincroniza sitios a servidores remotos usando Rsync. El servidor
|
|
|
|
# remoto tiene que tener rsync instalado.
|
|
|
|
class DeployRsync < Deploy
|
2022-04-06 21:27:52 +00:00
|
|
|
store :values, accessors: %i[destination host_keys], coder: JSON
|
2022-04-06 19:39:56 +00:00
|
|
|
|
|
|
|
def deploy
|
|
|
|
ssh? && rsync
|
|
|
|
end
|
|
|
|
|
2022-04-06 23:44:46 +00:00
|
|
|
# El espacio remoto es el mismo que el local
|
2022-04-06 19:39:56 +00:00
|
|
|
#
|
|
|
|
# @return [Integer]
|
|
|
|
def size
|
2022-04-06 23:44:46 +00:00
|
|
|
deploy_local.build_stats.last.size
|
2022-04-06 19:39:56 +00:00
|
|
|
end
|
|
|
|
|
2022-04-06 21:26:41 +00:00
|
|
|
# Devolver el destino o lanzar un error si no está configurado
|
|
|
|
def destination
|
|
|
|
values[:destination].tap do |d|
|
|
|
|
raise(ArgumentError, 'destination no está configurado') if d.blank?
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-04-06 19:39:56 +00:00
|
|
|
private
|
|
|
|
|
|
|
|
# Verificar la conexión SSH implementando Trust On First Use
|
|
|
|
#
|
|
|
|
# TODO: Medir el tiempo que tarda en iniciarse la conexión
|
|
|
|
#
|
|
|
|
# @return [Boolean]
|
|
|
|
def ssh?
|
|
|
|
user, host = user_host
|
|
|
|
ssh_available = false
|
|
|
|
|
2022-04-06 21:07:45 +00:00
|
|
|
Net::SSH.start(host, user, verify_host_key: tofu, timeout: 5) do |ssh|
|
2022-04-06 19:39:56 +00:00
|
|
|
if values[:host_keys].blank?
|
|
|
|
# Guardar las llaves que se encontraron en la primera conexión
|
|
|
|
values[:host_keys] = ssh.transport.host_keys.map do |host_key|
|
|
|
|
"#{host_key.ssh_type} #{host_key.fingerprint}"
|
|
|
|
end
|
|
|
|
|
|
|
|
ssh_available = save
|
|
|
|
else
|
|
|
|
ssh_available = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
ssh_available
|
|
|
|
rescue Exception => e
|
|
|
|
ExceptionNotifier.notify_exception(e, data: { site: site.id, hostname: host, user: user })
|
|
|
|
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
2022-04-06 20:23:42 +00:00
|
|
|
def env
|
|
|
|
{
|
|
|
|
'HOME' => home_dir,
|
|
|
|
'PATH' => '/usr/bin',
|
|
|
|
'LANG' => ENV['LANG']
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2022-04-06 19:39:56 +00:00
|
|
|
# Confiar en la primera llave que encontremos, fallar si cambian
|
|
|
|
#
|
|
|
|
# @return [Symbol]
|
|
|
|
def tofu
|
|
|
|
values[:host_keys].present? ? :always : :accept_new
|
|
|
|
end
|
|
|
|
|
|
|
|
# Devuelve el par user host
|
|
|
|
#
|
|
|
|
# @return [Array]
|
|
|
|
def user_host
|
|
|
|
destination.split(':', 2).first.split('@', 2).tap do |d|
|
|
|
|
next unless d.size == 1
|
|
|
|
|
|
|
|
d.insert(0, nil)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-04-06 21:27:52 +00:00
|
|
|
# Sincroniza hacia el directorio remoto
|
2022-04-06 19:39:56 +00:00
|
|
|
#
|
|
|
|
# @return [Boolean]
|
|
|
|
def rsync
|
2022-04-06 21:27:52 +00:00
|
|
|
run %(rsync -avi --timeout=5 #{Shellwords.escape source}/ #{Shellwords.escape destination}/)
|
2022-04-06 19:39:56 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# El origen es el destino de la compilación
|
|
|
|
#
|
|
|
|
# @return [String]
|
|
|
|
def source
|
2022-04-06 23:44:46 +00:00
|
|
|
deploy_local.destination
|
|
|
|
end
|
|
|
|
|
|
|
|
def deploy_local
|
|
|
|
@deploy_local ||= site.deploys.find_by(type: 'DeployLocal')
|
2022-04-06 19:39:56 +00:00
|
|
|
end
|
|
|
|
end
|