This repository has been archived by the owner on Apr 7, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
cluster.cr
116 lines (95 loc) · 2.8 KB
/
cluster.cr
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
module Bitte
class Cluster
include CLI::Helpers
property flake : String
property name : String
property region : String
property profile : String
property nodes = Hash(String, Node).new
getter hydrated = false
def initialize(@profile, @region, @flake, @name)
populate
hydrate
end
def asg_nodes
aws_asgs.flat_map { |asg|
instances = aws_client.describe_instances(
asg.instances.map(&.instance_id)
).reservations.map(&.instances).flatten
asg.instances.map do |asgi|
i = instances.find { |instance| instance.instance_id == asgi.instance_id }
next unless i
tags = i.tags_hash
if i && tags["Cluster"]? == self.name
Node.new(
cluster: self,
name: asgi.instance_id,
private_ip: i.private_ip_address.not_nil!,
public_ip: i.public_ip_address,
).tap { |node| node.tags = tags }
else
raise "Can't find #{asgi.instance_id}"
end
end
}.compact
end
def populate
nix_eval "#{flake}#clusters.#{name}.topology.nodes" do |output|
Hash(String, TopologyNode).from_json(output.to_s).each do |name, node|
nodes[name] = Node.new(
cluster: self,
name: name,
private_ip: node.private_ip
)
end
end
end
def hydrate
return if hydrated
mem = IO::Memory.new
sh!("terraform", args: ["output", "-json", "instances"], output: mem)
ips = Hash(String, String).from_json(mem.to_s)
ips.each do |node_name, ip|
@nodes[node_name].public_ip = ip
end
aws_instances.each do |instance|
tags = instance.tags_hash
next if tags["aws:autoscaling:groupName"]?
next unless tags["Cluster"]? == name
next unless public_ip = instance.public_ip_address
next unless node_name = tags["Name"]?
@nodes[node_name].public_ip = public_ip
@nodes[node_name].tags = tags
end
hydrated = true
end
def [](node_name)
nodes[node_name]
end
def aws_asgs
aws_client.auto_scaling_groups.auto_scaling_groups
end
def aws_instances
aws_client.describe_instances.reservations.map(&.instances).flatten
end
def aws_client
AWS::Client.new(region: region, profile: profile)
end
class Node
include CLI::Helpers
property cluster : Cluster
property name : String
property public_ip : String?
property private_ip : String
property tags = Hash(String, String).new
def initialize(@cluster, @name, @private_ip, @public_ip = nil)
end
def uid
tags["UID"]
end
def region
cluster.region
end
end
end
end