Module: SSHKitDslRoles

Defined in:
lib/kamal/sshkit_with_ext.rb

Instance Method Summary collapse

Instance Method Details

#on_roles(roles, hosts:, parallel: true, &block) ⇒ Object

Execute on hosts grouped by role.

Unlike on() which deduplicates hosts, this allows the same host to have multiple concurrent connections when it appears in multiple roles.

Options:

hosts: The hosts to run on (required)
parallel: When true, each role runs in its own thread with separate
        connections. When false, hosts run in parallel but roles on each
        host run sequentially (default: true)

Example:

on_roles(roles) do |host, role|
# deploy role to host
end


236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/kamal/sshkit_with_ext.rb', line 236

def on_roles(roles, hosts:, parallel: true, &block)
  if parallel
    threads = roles.filter_map do |role|
      if (role_hosts = role.hosts & hosts).any?
        Thread.new do
          on(role_hosts) { |host| instance_exec(host, role, &block) }
        rescue StandardError => e
          raise SSHKit::Runner::ExecuteError.new(e), "Exception while executing on #{role}: #{e.message}"
        end
      end
    end

    exceptions = []
    threads.each do |t|
      begin
        t.join
      rescue SSHKit::Runner::ExecuteError => e
        exceptions << e
      end
    end

    if exceptions.one?
      raise exceptions.first
    elsif exceptions.many?
      raise exceptions.first, [ "Exceptions on #{exceptions.count} roles:", exceptions.map(&:message) ].join("\n")
    end
  else
    # Host-first iteration: hosts run in parallel, roles on each host run sequentially
    on(hosts) do |host|
      roles.each do |role|
        instance_exec(host, role, &block) if role.hosts.include?(host.to_s)
      end
    end
  end
end