blob: 0e23831db3326d51c9ffdc2a1e23c5d93d5a37f1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
# encoding: utf-8
##
## node related macros
##
module LeapCli
module Macro
#
# the list of all the nodes
#
def nodes
env.nodes
end
#
# simple alias for global.provider
#
def provider
env.provider
end
#
# returns a list of nodes that match the same environment
#
# if @node.environment is not set, we return other nodes
# where environment is not set.
#
def nodes_like_me
nodes[:environment => @node.environment]
end
#
# returns a list of nodes that match the location name
# and environment of @node.
#
def nodes_near_me
if @node['location'] && @node['location']['name']
nodes_like_me['location.name' => @node.location.name]
else
nodes_like_me['location' => nil]
end
end
#
#
# picks a node out from the node list in such a way that:
#
# (1) which nodes picked which nodes is saved in secrets.json
# (2) when other nodes call this macro with the same node list, they are guaranteed to get a different node
# (3) if all the nodes in the pick_node list have been picked, remaining nodes are distributed randomly.
#
# if the node_list is empty, an exception is raised.
# if node_list size is 1, then that node is returned and nothing is
# memorized via the secrets.json file.
#
# `label` is needed to distinguish between pools of nodes for different purposes.
#
# TODO: more evenly balance after all the nodes have been picked.
#
def pick_node(label, node_list)
if node_list.any?
if node_list.size == 1
return node_list.values.first
else
secrets_key = "pick_node(:#{label},#{node_list.keys.sort.join(',')})"
secrets_value = @manager.secrets.retrieve(secrets_key, @node.environment) || {}
secrets_value[@node.name] ||= begin
node_to_pick = nil
node_list.each_node do |node|
next if secrets_value.values.include?(node.name)
node_to_pick = node.name
end
node_to_pick ||= secrets_value.values.shuffle.first # all picked already, so pick a random one.
node_to_pick
end
picked_node_name = secrets_value[@node.name]
@manager.secrets.set(secrets_key, secrets_value, @node.environment)
return node_list[picked_node_name]
end
else
raise ArgumentError.new('pick_node(node_list): node_list cannot be empty')
end
end
end
end
|