Class: Nvoi::External::Dns::Cloudflare
- Inherits:
-
Object
- Object
- Nvoi::External::Dns::Cloudflare
- Defined in:
- lib/nvoi/external/dns/cloudflare.rb
Overview
Cloudflare handles Cloudflare API operations for DNS and tunnels
Constant Summary collapse
- BASE_URL =
"https://api.cloudflare.com/client/v4"
Instance Attribute Summary collapse
-
#account_id ⇒ Object
readonly
Returns the value of attribute account_id.
Instance Method Summary collapse
- #create_dns_record(zone_id, name, record_type, content, proxied: true) ⇒ Object
- #create_or_update_dns_record(zone_id, name, record_type, content, proxied: true) ⇒ Object
-
#create_tunnel(name) ⇒ Object
Tunnel operations.
- #delete_dns_record(zone_id, record_id) ⇒ Object
- #delete_tunnel(tunnel_id) ⇒ Object
- #find_dns_record(zone_id, name, record_type) ⇒ Object
- #find_tunnel(name) ⇒ Object
- #find_zone(domain) ⇒ Object
- #get_tunnel_token(tunnel_id) ⇒ Object
-
#initialize(token, account_id) ⇒ Cloudflare
constructor
A new instance of Cloudflare.
-
#list_zones ⇒ Object
DNS operations.
- #subdomain_available?(zone_id, subdomain, domain) ⇒ Boolean
- #update_dns_record(zone_id, record_id, name, record_type, content, proxied: true) ⇒ Object
- #update_tunnel_configuration(tunnel_id, hostnames, service_url) ⇒ Object
-
#validate_credentials ⇒ Object
Validation.
- #verify_tunnel_configuration(tunnel_id, expected_hostnames, expected_service, max_attempts) ⇒ Object
Constructor Details
#initialize(token, account_id) ⇒ Cloudflare
Returns a new instance of Cloudflare.
16 17 18 19 20 21 22 23 24 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 16 def initialize(token, account_id) @token = token @account_id = account_id @conn = Faraday.new(url: BASE_URL) do |f| f.request :json f.response :json f.adapter Faraday.default_adapter end end |
Instance Attribute Details
#account_id ⇒ Object (readonly)
Returns the value of attribute account_id.
14 15 16 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 14 def account_id @account_id end |
Instance Method Details
#create_dns_record(zone_id, name, record_type, content, proxied: true) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 176 def create_dns_record(zone_id, name, record_type, content, proxied: true) url = "zones/#{zone_id}/dns_records" response = post(url, { type: record_type, name:, content:, proxied:, ttl: 1 }) result = response["result"] Types::Record.new( id: result["id"], type: result["type"], name: result["name"], content: result["content"], proxied: result["proxied"], ttl: result["ttl"] ) end |
#create_or_update_dns_record(zone_id, name, record_type, content, proxied: true) ⇒ Object
220 221 222 223 224 225 226 227 228 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 220 def create_or_update_dns_record(zone_id, name, record_type, content, proxied: true) existing = find_dns_record(zone_id, name, record_type) if existing update_dns_record(zone_id, existing.id, name, record_type, content, proxied:) else create_dns_record(zone_id, name, record_type, content, proxied:) end end |
#create_tunnel(name) ⇒ Object
Tunnel operations
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 28 def create_tunnel(name) url = "accounts/#{@account_id}/cfd_tunnel" tunnel_secret = generate_tunnel_secret response = post(url, { name:, tunnel_secret:, config_src: "cloudflare" }) result = response["result"] Types::Tunnel::Record.new( id: result["id"], name: result["name"], token: result["token"] ) end |
#delete_dns_record(zone_id, record_id) ⇒ Object
230 231 232 233 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 230 def delete_dns_record(zone_id, record_id) url = "zones/#{zone_id}/dns_records/#{record_id}" delete(url) end |
#delete_tunnel(tunnel_id) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 111 def delete_tunnel(tunnel_id) # Clean up all connections first connections_url = "accounts/#{@account_id}/cfd_tunnel/#{tunnel_id}/connections" begin delete(connections_url) rescue StandardError # Ignore connection cleanup errors end # Now delete the tunnel url = "accounts/#{@account_id}/cfd_tunnel/#{tunnel_id}" delete(url) end |
#find_dns_record(zone_id, name, record_type) ⇒ Object
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 156 def find_dns_record(zone_id, name, record_type) url = "zones/#{zone_id}/dns_records" response = get(url) results = response["result"] return nil unless results record_data = results.find { |r| r["name"] == name && r["type"] == record_type } return nil unless record_data Types::Record.new( id: record_data["id"], type: record_data["type"], name: record_data["name"], content: record_data["content"], proxied: record_data["proxied"], ttl: record_data["ttl"] ) end |
#find_tunnel(name) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 46 def find_tunnel(name) url = "accounts/#{@account_id}/cfd_tunnel" response = get(url, { name:, is_deleted: false }) results = response["result"] return nil if results.nil? || results.empty? result = results[0] Types::Tunnel::Record.new( id: result["id"], name: result["name"], token: result["token"] ) end |
#find_zone(domain) ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 137 def find_zone(domain) url = "zones" response = get(url) results = response["result"] return nil unless results zone_data = results.find { |z| z["name"] == domain } return nil unless zone_data Types::Zone.new(id: zone_data["id"], name: zone_data["name"]) end |
#get_tunnel_token(tunnel_id) ⇒ Object
61 62 63 64 65 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 61 def get_tunnel_token(tunnel_id) url = "accounts/#{@account_id}/cfd_tunnel/#{tunnel_id}/token" response = get(url) response["result"] end |
#list_zones ⇒ Object
DNS operations
127 128 129 130 131 132 133 134 135 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 127 def list_zones url = "zones" response = get(url) results = response["result"] || [] results.map do |z| { id: z["id"], name: z["name"], status: z["status"] } end end |
#subdomain_available?(zone_id, subdomain, domain) ⇒ Boolean
150 151 152 153 154 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 150 def subdomain_available?(zone_id, subdomain, domain) fqdn = subdomain.empty? ? domain : "#{subdomain}.#{domain}" # Check for CNAME or A record !find_dns_record(zone_id, fqdn, "CNAME") && !find_dns_record(zone_id, fqdn, "A") end |
#update_dns_record(zone_id, record_id, name, record_type, content, proxied: true) ⇒ Object
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 198 def update_dns_record(zone_id, record_id, name, record_type, content, proxied: true) url = "zones/#{zone_id}/dns_records/#{record_id}" response = patch(url, { type: record_type, name:, content:, proxied:, ttl: 1 }) result = response["result"] Types::Record.new( id: result["id"], type: result["type"], name: result["name"], content: result["content"], proxied: result["proxied"], ttl: result["ttl"] ) end |
#update_tunnel_configuration(tunnel_id, hostnames, service_url) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 67 def update_tunnel_configuration(tunnel_id, hostnames, service_url) hostnames = Array(hostnames) url = "accounts/#{@account_id}/cfd_tunnel/#{tunnel_id}/configurations" ingress_rules = hostnames.map do |hostname| rule = { hostname:, service: service_url } # Only set httpHostHeader for non-wildcard hostnames # Wildcards should pass through the original Host header rule[:originRequest] = { httpHostHeader: hostname } unless hostname.start_with?("*.") rule end ingress_rules << { service: "http_status:404" } config = { ingress: ingress_rules } put(url, { config: }) end |
#validate_credentials ⇒ Object
Validation
237 238 239 240 241 242 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 237 def validate_credentials get("user/tokens/verify") true rescue Errors::CloudflareError => e raise Errors::ValidationError, "cloudflare credentials invalid: #{e.message}" end |
#verify_tunnel_configuration(tunnel_id, expected_hostnames, expected_service, max_attempts) ⇒ Object
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 |
# File 'lib/nvoi/external/dns/cloudflare.rb', line 84 def verify_tunnel_configuration(tunnel_id, expected_hostnames, expected_service, max_attempts) expected_hostnames = Array(expected_hostnames) url = "accounts/#{@account_id}/cfd_tunnel/#{tunnel_id}/configurations" max_attempts.times do begin response = get(url) if response["success"] config = response.dig("result", "config") ingress = config&.dig("ingress") || [] configured_hostnames = ingress.map { |r| r["hostname"] }.compact if expected_hostnames.all? { |h| configured_hostnames.include?(h) } return true end end rescue StandardError # Continue retrying end sleep(2) end raise Errors::TunnelError, "tunnel configuration not propagated after #{max_attempts} attempts" end |