Class: Capistrano::Upload

Inherits:
Object
  • Object
show all
Defined in:
lib/capistrano/upload.rb

Overview

This class encapsulates a single file upload to be performed in parallel across multiple machines, using the SFTP protocol. Although it is intended to be used primarily from within Capistrano, it may also be used standalone if you need to simply upload a file to multiple servers.

Basic Usage:

begin
  uploader = Capistrano::Upload.new(sessions, "remote-file.txt",
      :data => "the contents of the file to upload")
  uploader.process!
rescue Capistrano::UploadError => e
  warn "Could not upload the file: #{e.message}"
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sessions, filename, options) ⇒ Upload

Creates and prepares a new Upload instance. The sessions parameter must be an array of open Net::SSH sessions. The filename is the name (including path) of the destination file on the remote server. The options hash accepts the following keys (as symbols):

  • data: required. Should refer to a String containing the contents of the file to upload.

  • mode: optional. The “mode” of the destination file. Defaults to 0664.

  • logger: optional. Should point to a Capistrano::Logger instance, if given.

Raises:

  • (ArgumentError)


54
55
56
57
58
59
60
61
62
63
# File 'lib/capistrano/upload.rb', line 54

def initialize(sessions, filename, options)
  raise ArgumentError, "you must specify the data to upload via the :data option" unless options[:data]

  @sessions = sessions
  @filename = filename
  @options  = options

  @completed = @failed = 0
  @sftps = setup_sftp
end

Instance Attribute Details

#completedObject (readonly)

Returns the value of attribute completed.



42
43
44
# File 'lib/capistrano/upload.rb', line 42

def completed
  @completed
end

#failedObject (readonly)

Returns the value of attribute failed.



42
43
44
# File 'lib/capistrano/upload.rb', line 42

def failed
  @failed
end

#filenameObject (readonly)

Returns the value of attribute filename.



41
42
43
# File 'lib/capistrano/upload.rb', line 41

def filename
  @filename
end

#optionsObject (readonly)

Returns the value of attribute options.



41
42
43
# File 'lib/capistrano/upload.rb', line 41

def options
  @options
end

#sessionsObject (readonly)

Returns the value of attribute sessions.



41
42
43
# File 'lib/capistrano/upload.rb', line 41

def sessions
  @sessions
end

Class Method Details

.process(sessions, filename, options) ⇒ Object



37
38
39
# File 'lib/capistrano/upload.rb', line 37

def self.process(sessions, filename, options)
  new(sessions, filename, options).process!
end

Instance Method Details

#process!Object

Uploads to all specified servers in parallel. If any one of the servers fails, an exception will be raised (UploadError).



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/capistrano/upload.rb', line 67

def process!
  logger.debug "uploading #{filename}" if logger
  while running?
    @sftps.each do |sftp|
      next if sftp.channel[:done]
      begin
        sftp.channel.connection.process(true)
      rescue Net::SFTP::Operations::StatusException => error
        logger.important "uploading failed: #{error.description}", sftp.channel[:server] if logger
        failed!(sftp)
      end
    end
    sleep 0.01 # a brief respite, to keep the CPU from going crazy
  end
  logger.trace "upload finished" if logger

  if (failed = @sftps.select { |sftp| sftp.channel[:failed] }).any?
    hosts = failed.map { |sftp| sftp.channel[:server] }
    error = UploadError.new("upload of #{filename} failed on #{hosts.join(',')}")
    error.hosts = hosts
    raise error
  end

  self
end