Created
December 16, 2024 08:39
-
-
Save ynott/fa33d36f26f0e5c00f69c65564dbb456 to your computer and use it in GitHub Desktop.
Ruby script that retrieves PowerDNS records and saves them in YML format (PowerDNSに保存されている既存のレコードを取得してYML形式で保存するRubyスクリプト)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'net/http' | |
require 'uri' | |
require 'json' | |
require 'yaml' | |
# UNSET Proxy | |
ENV['http_proxy'] = '' | |
ENV['https_proxy'] = '' | |
# PowerDNS APIの設定 | |
API_URL = 'http://localhost:8081' # PowerDNS API URL | |
API_KEY = 'password' # API Secret here. | |
SERVER_ID = 'localhost' # Server ID ( Normally 'localhost' ) | |
# リクエスト用ヘッダー | |
HEADERS = { | |
'X-API-Key' => API_KEY, | |
'Content-Type' => 'application/json', | |
'Accept' => 'application/json' | |
} | |
# デバッグモード | |
DEBUG = false | |
# HTTP接続のセットアップ | |
def setup_http_connection(uri) | |
http = Net::HTTP.new(uri.host, uri.port) | |
http.open_timeout = 5 # 接続タイムアウトを5秒に設定 | |
http.read_timeout = 10 # 読み取りタイムアウトを10秒に設定 | |
http | |
end | |
# APIリクエストの実行 | |
def make_api_request(uri, request_type = :get) | |
http = setup_http_connection(uri) | |
request = case request_type | |
when :get | |
Net::HTTP::Get.new(uri.request_uri, HEADERS) | |
else | |
raise "Unsupported request type: #{request_type}" | |
end | |
begin | |
puts "Making request to: #{uri}" if DEBUG | |
response = http.request(request) | |
unless response.is_a?(Net::HTTPSuccess) | |
raise "API request failed: #{response.code} - #{response.message}" | |
end | |
puts "Response body: #{response.body}" if DEBUG | |
JSON.parse(response.body) | |
rescue JSON::ParserError => e | |
raise "Failed to parse API response: #{e.message}" | |
rescue => e | |
raise "API request error: #{e.message}" | |
end | |
end | |
# ゾーン一覧の取得 | |
def fetch_zones | |
begin | |
uri = URI.parse("#{API_URL}/servers/#{SERVER_ID}/zones") | |
response_data = make_api_request(uri) | |
response_data.map { |zone| zone['id'] } | |
rescue => e | |
puts "Error fetching zones: #{e.message}" | |
exit 1 | |
end | |
end | |
# 個別ゾーンの詳細を取得(レコードを含む) | |
def fetch_zone_details(zone_id) | |
begin | |
uri = URI.parse("#{API_URL}/servers/#{SERVER_ID}/zones/#{URI.encode_www_form_component(zone_id)}") | |
zone_data = make_api_request(uri) | |
puts "\nZone data keys: #{zone_data.keys}" if DEBUG | |
# Ansibleプレイブック形式に変換 | |
formatted_data = { | |
'name' => zone_data['name'], | |
'properties' => { | |
'kind' => zone_data['kind'], | |
'nameservers' => [], # NS レコードから抽出 | |
'soa' => {}, # SOA レコードから抽出 | |
'rrsets' => [] | |
} | |
} | |
if zone_data['rrsets'] | |
zone_data['rrsets'].each do |rrset| | |
case rrset['type'] | |
when 'SOA' | |
# SOAレコードの処理 | |
if rrset['records'] && !rrset['records'].empty? | |
soa_parts = rrset['records'].first['content'].split(' ') | |
formatted_data['properties']['soa'] = { | |
'mname' => soa_parts[0], | |
'rname' => soa_parts[1] | |
} | |
end | |
when 'NS' | |
# NSレコードの処理 | |
formatted_data['properties']['nameservers'] = rrset['records'].map { |r| r['content'] } | |
else | |
# その他のレコードの処理 | |
formatted_data['properties']['rrsets'] << { | |
'name' => rrset['name'], | |
'type' => rrset['type'], | |
'records' => rrset['records'].map { |r| { 'content' => r['content'] } } | |
} | |
end | |
end | |
end | |
formatted_data | |
rescue => e | |
puts "Error fetching details for zone #{zone_id}: #{e.message}" | |
nil | |
end | |
end | |
# ゾーンごとのレコードをYAML形式で保存 | |
def save_zones_to_yaml(zone_ids) | |
# スクリプトのディレクトリを取得 | |
script_dir = File.dirname(File.expand_path(__FILE__)) | |
zone_ids.each do |zone_id| | |
begin | |
puts "\nProcessing zone: #{zone_id}" if DEBUG | |
# 各ゾーンの詳細情報を取得 | |
zone = fetch_zone_details(zone_id) | |
next unless zone | |
# ゾーン名からファイル名を生成し、スクリプトのディレクトリと結合 | |
file_name = "backup_#{zone['name'].chomp('.').gsub('/', '_')}.yaml" | |
full_path = File.join(script_dir, file_name) | |
# YAMLデータの生成 | |
yaml_data = zone.to_yaml | |
# デバッグ情報 | |
if DEBUG | |
puts "Zone data to be saved:" | |
puts yaml_data | |
puts "✓ Successfully saved #{file_name} (#{zone['properties']['rrsets']&.length || 0} records)" | |
else | |
puts zone['name'].chomp('.') | |
end | |
# ファイルに書き込み | |
File.open(full_path, 'w') { |file| file.write(yaml_data) } | |
rescue => e | |
puts "× Failed to save zone #{zone_id}: #{e.message}" | |
end | |
end | |
end | |
# メイン処理 | |
begin | |
puts "Starting PowerDNS backup process..." if DEBUG | |
puts "Connecting to PowerDNS API at #{API_URL}" if DEBUG | |
zone_ids = fetch_zones | |
if zone_ids.empty? | |
puts "Warning: No zones found" if DEBUG | |
exit 0 | |
end | |
puts "Found #{zone_ids.length} zones" if DEBUG | |
save_zones_to_yaml(zone_ids) | |
puts "Backup process completed successfully" if DEBUG | |
rescue => e | |
puts "Fatal error: #{e.message}" | |
exit 1 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment