-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
157 lines (132 loc) · 3.47 KB
/
main.go
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package main
import (
"bytes"
"encoding/json"
"fmt"
"net"
"net/http"
"os"
"strconv"
"time"
)
const (
defaultTTL = 300
)
type Record struct {
Content string `json:"content"`
Name string `json:"name"`
TTL int `json:"ttl"`
Type string `json:"type"`
Disabled bool `json:"disabled"`
}
type RRSet struct {
Name string `json:"name"`
Type string `json:"type"`
TTL int `json:"ttl"`
ChangeType string `json:"changetype"`
Records []Record `json:"records"`
}
type DNSUpdate struct {
RRSets []RRSet `json:"rrsets"`
}
func getLocalIPAddress(interfaceName string) (string, error) {
iface, err := net.InterfaceByName(interfaceName)
if err != nil {
return "", fmt.Errorf("failed to get interface: %v", err)
}
addrs, err := iface.Addrs()
if err != nil {
return "", fmt.Errorf("failed to get addresses: %v", err)
}
for _, addr := range addrs {
switch v := addr.(type) {
case *net.IPNet:
if v.IP.To4() != nil {
return v.IP.String(), nil
}
}
}
return "", fmt.Errorf("no valid IPv4 address found for interface %s", interfaceName)
}
func main() {
// Get environment variables
apiKey := os.Getenv("PDNS_API_KEY")
ownName := os.Getenv("PDNS_OWN_NAME")
pdnsServer := os.Getenv("PDNS_SERVER")
interfaceName := os.Getenv("PDNS_INTERFACE")
ttlStr := os.Getenv("PDNS_TTL")
zoneName := os.Getenv("PDNS_ZONE")
if apiKey == "" || ownName == "" || pdnsServer == "" || interfaceName == "" || zoneName == "" {
fmt.Println("Please set the environment variables PDNS_API_KEY, PDNS_OWN_NAME, PDNS_SERVER, PDNS_INTERFACE, and PDNS_ZONE")
return
}
// Parse TTL or use default
ttl := defaultTTL
if ttlStr != "" {
ttlParsed, err := strconv.Atoi(ttlStr)
if err == nil {
ttl = ttlParsed
}
}
for {
// Get local IP address
localIP, err := getLocalIPAddress(interfaceName)
if err != nil {
fmt.Printf("Error getting local IP address: %v\n", err)
return
}
// Create record
record := Record{
Content: localIP,
Name: fmt.Sprintf("%s.%s.", ownName, zoneName),
TTL: ttl,
Type: "A",
Disabled: false,
}
rrset := RRSet{
Name: record.Name,
Type: record.Type,
TTL: record.TTL,
ChangeType: "REPLACE",
Records: []Record{record},
}
update := DNSUpdate{
RRSets: []RRSet{rrset},
}
// Encode to JSON
body, err := json.Marshal(update)
if err != nil {
fmt.Printf("Error encoding JSON: %v\n", err)
return
}
// Send request to PowerDNS server
powerDNSAPIURL := fmt.Sprintf("http://%s/api/v1/servers/localhost/zones/%s", pdnsServer, zoneName)
req, err := http.NewRequest("PATCH", powerDNSAPIURL, bytes.NewBuffer(body))
if err != nil {
fmt.Printf("Error creating request: %v\n", err)
return
}
// Set headers
req.Header.Set("X-API-Key", apiKey)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error sending request: %v\n", err)
return
}
defer resp.Body.Close()
// Check response
if resp.StatusCode != http.StatusNoContent {
fmt.Printf("Request failed: status code %d\n", resp.StatusCode)
} else {
fmt.Println("Resource record updated successfully!")
}
// Sleep for 30 minutes
// TODO: 時間を上書きできるようにする
fmt.Println("Successfully updated DNS record!")
fmt.Println("IP: ", localIP)
fmt.Println("Sleeping for 30 minutes...")
time.Sleep(30 * time.Minute)
}
}