mirror of
https://github.com/czhu12/canine.git
synced 2025-12-16 16:35:10 -06:00
77 lines
2.6 KiB
Ruby
77 lines
2.6 KiB
Ruby
class Networks::CheckDns
|
|
extend LightService::Action
|
|
expects :ingress, :connection
|
|
|
|
class << self
|
|
def infer_expected_dns(ingress, connection)
|
|
ingress.connect(connection)
|
|
dns_record = ingress.hostname
|
|
|
|
if dns_record[:type] == :ip_address && is_private_ip?(dns_record[:value])
|
|
cluster = ingress.service.project.cluster
|
|
# This only works if it is a single node cluster like k3s
|
|
public_ip = infer_public_ip_from_cluster(connection)
|
|
dns_record = {
|
|
value: public_ip,
|
|
type: :ip_address
|
|
}
|
|
end
|
|
dns_record
|
|
end
|
|
|
|
def is_private_ip?(ip)
|
|
ip.starts_with?("10.") || ip.starts_with?("172.") || ip.starts_with?("192.")
|
|
end
|
|
|
|
def infer_public_ip_from_cluster(connection)
|
|
# The ingress is reporting a private IP address, so we need to guess the public IP address
|
|
# based on the cluster's domain name
|
|
server_name = K8::Client.new(connection).server
|
|
# Parse the hostname from the server, with ruby's URI.parse
|
|
hostname = URI.parse(server_name).hostname
|
|
# If hostname is just an ip address, then we can return it
|
|
if ip?(hostname)
|
|
hostname
|
|
else
|
|
# Otherwise, we need to use Resolv to get the public IP address
|
|
Resolv.getaddress(hostname)
|
|
end
|
|
end
|
|
|
|
def ip?(ip)
|
|
ip.match?(/\A\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/)
|
|
end
|
|
end
|
|
|
|
executed do |context|
|
|
# TODO
|
|
expected_dns = infer_expected_dns(context.ingress, context.connection)
|
|
context.ingress.service.domains.each do |domain|
|
|
if expected_dns[:type] == :ip_address
|
|
ip_addresses = Resolv::DNS.open do |dns|
|
|
dns.getresources(domain.domain_name, Resolv::DNS::Resource::IN::A).map do |resource|
|
|
resource.address
|
|
end
|
|
end
|
|
|
|
if ip_addresses.any? && ip_addresses.first.to_s == expected_dns[:value]
|
|
domain.update(status: :dns_verified)
|
|
else
|
|
domain.update(status: :dns_incorrect, status_reason: "DNS record (#{ip_addresses.first || "empty"}) does not match expected IP address (#{expected_dns[:value]})")
|
|
end
|
|
else
|
|
hostnames = Resolv::DNS.open do |dns|
|
|
dns.getresources(domain.domain_name, Resolv::DNS::Resource::IN::CNAME).map do |resource|
|
|
resource.name
|
|
end
|
|
end
|
|
if hostnames.any? && hostnames.first.to_s == expected_dns[:value]
|
|
domain.update(status: :dns_verified)
|
|
else
|
|
domain.update(status: :dns_incorrect, status_reason: "DNS record (#{hostnames.first || "empty"}) does not match expected hostname (#{expected_dns[:value]})")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|