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


230
231
232
233
234
235
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
# File 'lib/kamal/sshkit_with_ext.rb', line 230

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