Class: EY::Serverside::Servers

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable
Defined in:
lib/engineyard-serverside/servers.rb

Defined Under Namespace

Classes: DuplicateHostname

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(servers) ⇒ Servers

Returns a new instance of Servers.



35
36
37
38
# File 'lib/engineyard-serverside/servers.rb', line 35

def initialize(servers)
  @servers = servers
  @cache = {}
end

Class Method Details

.from_hashes(server_hashes) ⇒ Object



25
26
27
28
29
30
31
32
33
# File 'lib/engineyard-serverside/servers.rb', line 25

def self.from_hashes(server_hashes)
  servers = server_hashes.inject({}) do |memo, server_hash|
    server = Server.from_hash(server_hash)
    raise DuplicateHostname.new(server.hostname) if memo.key?(server.hostname)
    memo[server.hostname] = server
    memo
  end
  new(servers.values)
end

Instance Method Details

#==(other) ⇒ Object



22
# File 'lib/engineyard-serverside/servers.rb', line 22

def ==(other) other.respond_to?(:to_a) && other.to_a == to_a end

#localhostObject



40
41
42
# File 'lib/engineyard-serverside/servers.rb', line 40

def localhost
  @servers.find {|server| server.local? }
end

#map_in_parallel(&block) ⇒ Object

Makes a thread for each server and executes the block, returning an array of return values



83
84
85
86
# File 'lib/engineyard-serverside/servers.rb', line 83

def map_in_parallel(&block)
  threads = map { |server| Thread.new { block.call(server) } }
  threads.map { |t| t.value }
end

#reject(*a, &b) ⇒ Object



20
# File 'lib/engineyard-serverside/servers.rb', line 20

def reject(*a, &b) self.class.new @servers.reject(*a,&b) end

#remoteObject



44
45
46
# File 'lib/engineyard-serverside/servers.rb', line 44

def remote
  reject { |server| server.local? }
end

#roles(*select_roles, &block) ⇒ Object

We look up the same set of servers over and over. Cache them so we don't have to find them every time Accepts a block (because it's confusing when you send a block to this method and it doesn't yield and it's better than raising)



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/engineyard-serverside/servers.rb', line 52

def roles(*select_roles, &block)
  if block_given?
    return yield(roles(*select_roles))
  end

  roles_set = Set.new select_roles.flatten.compact.map{|r| r.to_sym}
  if roles_set.empty? || roles_set.include?(:all)
    self
  else
    @cache[roles_set] ||= select { |server| server.matches_roles?(roles_set) }
  end
end

#run(shell, cmd, &block) ⇒ Object

Run a command on this set of servers.



66
67
68
69
70
71
# File 'lib/engineyard-serverside/servers.rb', line 66

def run(shell, cmd, &block)
  run_on_each(shell) do |server|
    exec_cmd = server.command_on_server('sh -l -c', cmd, &block)
    shell.logged_system(exec_cmd, server)
  end
end

#run_on_each(shell, &block) ⇒ Object

Makes a theard for each server and executes the block, Assumes that the return value of the block is a CommandResult and ensures that all the command results were successful.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/engineyard-serverside/servers.rb', line 96

def run_on_each(shell, &block)
  results = map_in_parallel(&block)
  failures = results.reject {|result| result.success? }

  if failures.any?
    commands = failures.map { |f| f.command }.uniq
    servers = failures.map { |f| f.server }.compact.map { |s| s.inspect }
    outputs = failures.map { |f| f.output }.uniq
    message = "The following command#{commands.size == 1 ? '' : 's'} failed"
    if servers.any?
      message << " on server#{servers.size == 1 ? '' : 's'} [#{servers.join(', ')}]"
    end
    message << "\n\n"
    commands.each do |cmd|
      message << "$ #{cmd}\n"
    end
    message << "\n" << outputs.join("\n\n") << "\n"
    raise EY::Serverside::RemoteFailure.new(message)
  end
end

#select(*a, &b) ⇒ Object



19
# File 'lib/engineyard-serverside/servers.rb', line 19

def select(*a, &b) self.class.new @servers.select(*a,&b) end

#select_in_parallel(&block) ⇒ Object



88
89
90
91
# File 'lib/engineyard-serverside/servers.rb', line 88

def select_in_parallel(&block)
  results = map_in_parallel { |server| block.call(server) ? server : nil }.compact
  self.class.new results
end

#sudo(shell, cmd, &block) ⇒ Object

Run a sudo command on this set of servers.



74
75
76
77
78
79
# File 'lib/engineyard-serverside/servers.rb', line 74

def sudo(shell, cmd, &block)
  run_on_each(shell) do |server|
    exec_cmd = server.command_on_server('sudo sh -l -c', cmd, &block)
    shell.logged_system(exec_cmd, server)
  end
end

#to_aObject



21
# File 'lib/engineyard-serverside/servers.rb', line 21

def to_a() @servers end