Skip to content

Commit e137718

Browse files
authored
feat: TransIP support (#274)
* feat: TransIP support * style: make comments end with `.` * style: make error compatible with staticcheck
1 parent ecc7c08 commit e137718

File tree

7 files changed

+135
-0
lines changed

7 files changed

+135
-0
lines changed

README.md

+30
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
- [OVH](#ovh)
5454
- [Dynu](#dynu)
5555
- [IONOS](#ionos)
56+
- [TransIP](#transip)
5657
- [Notifications](#notifications)
5758
- [Email](#email)
5859
- [Telegram](#telegram)
@@ -110,6 +111,7 @@
110111
| [OVH][ovh] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
111112
| [Dynu][dynu] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
112113
| [IONOS][ionos] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
114+
| [TransIP][transip] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
113115

114116
[cloudflare]: https://cloudflare.com
115117
[digitalocean]: https://digitalocean.com
@@ -130,6 +132,7 @@
130132
[ovh]: https://www.ovh.com
131133
[dynu]: https://www.dynu.com/
132134
[ionos]: https://www.ionos.com/
135+
[transip]: https://www.transip.net/
133136

134137
Tip: You can follow this [issue](https://github.com/TimothyYe/godns/issues/76) to view the current status of DDNS for root domains.
135138

@@ -863,6 +866,33 @@ socks5_proxy: ""
863866
864867
</details>
865868
869+
#### TransIP
870+
871+
For TransIP, you need to provide your api private key as `login_token` and username as `email`, and configure all the domains & subdomains.
872+
873+
<details>
874+
<summary>Example</summary>
875+
876+
```yaml
877+
provider: TransIP
878+
email: account_name
879+
login_token: api_key
880+
domains:
881+
- domain_name: example.com
882+
sub_domains:
883+
- "@"
884+
- somesubdomain
885+
- anothersubdomain
886+
resolver: 1.1.1.1
887+
ip_urls:
888+
- https://api.ipify.org
889+
ip_type: IPv4
890+
interval: 300
891+
socks5_proxy: ""
892+
```
893+
894+
<details>
895+
866896
### Notifications
867897

868898
GoDNS can send a notification each time the IP changes.

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
require (
1919
github.com/fsnotify/fsnotify v1.8.0
2020
github.com/gofiber/fiber/v2 v2.52.6
21+
github.com/transip/gotransip/v6 v6.26.0
2122
)
2223

2324
require (

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
7171
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
7272
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
7373
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
74+
github.com/transip/gotransip/v6 v6.26.0 h1:Aejfvh8rSp8Mj2GX/RpdBjMCv+Iy/DmgfNgczPDP550=
75+
github.com/transip/gotransip/v6 v6.26.0/go.mod h1:x0/RWGRK/zob817O3tfO2xhFoP1vu8YOHORx6Jpk80s=
7476
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
7577
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
7678
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=

internal/provider/factory.go

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/TimothyYe/godns/internal/provider/ovh"
2323
"github.com/TimothyYe/godns/internal/provider/scaleway"
2424
"github.com/TimothyYe/godns/internal/provider/strato"
25+
"github.com/TimothyYe/godns/internal/provider/transip"
2526
"github.com/TimothyYe/godns/internal/settings"
2627
"github.com/TimothyYe/godns/internal/utils"
2728
)
@@ -68,6 +69,8 @@ func GetProvider(conf *settings.Settings) (IDNSProvider, error) {
6869
provider = &dynu.DNSProvider{}
6970
case utils.IONOS:
7071
provider = &ionos.DNSProvider{}
72+
case utils.TRANSIP:
73+
provider = &transip.DNSProvider{}
7174
default:
7275
return nil, fmt.Errorf("Unknown provider '%s'", conf.Provider)
7376
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package transip
2+
3+
import (
4+
"strings"
5+
6+
"github.com/TimothyYe/godns/internal/settings"
7+
"github.com/TimothyYe/godns/internal/utils"
8+
log "github.com/sirupsen/logrus"
9+
"github.com/transip/gotransip/v6"
10+
"github.com/transip/gotransip/v6/domain"
11+
)
12+
13+
const defaultTTL int = 60 // 60 seconds.
14+
15+
// DNSProvider struct.
16+
type DNSProvider struct {
17+
configuration *settings.Settings
18+
clientConfig gotransip.ClientConfiguration
19+
}
20+
21+
// Init passes DNS settings and store it to the provider instance.
22+
func (provider *DNSProvider) Init(conf *settings.Settings) {
23+
provider.configuration = conf
24+
provider.clientConfig = gotransip.ClientConfiguration{
25+
AccountName: conf.Email}
26+
if strings.HasPrefix(conf.LoginToken, "-----BEGIN PRIVATE KEY-----") { // Private Key.
27+
provider.clientConfig.PrivateKeyReader = strings.NewReader(conf.LoginToken)
28+
} else { // JWT.
29+
provider.clientConfig.Token = conf.LoginToken
30+
}
31+
}
32+
33+
// UpdateIP updates the IP address of the given subdomain.
34+
func (provider *DNSProvider) UpdateIP(domainName, subDomainName, ip string) error {
35+
client, err := gotransip.NewClient(provider.clientConfig)
36+
if err != nil {
37+
return err
38+
}
39+
domainRepo := domain.Repository{Client: client}
40+
41+
exists, ttl, err := checkExistence(domainRepo, subDomainName, domainName)
42+
if err != nil {
43+
return err
44+
}
45+
46+
if exists { // Update.
47+
err = domainRepo.UpdateDNSEntry(domainName, domain.DNSEntry{
48+
Name: subDomainName,
49+
Type: provider.setType(),
50+
Content: ip,
51+
Expire: ttl})
52+
if err != nil {
53+
log.Error("failed to update domain:", subDomainName)
54+
return err
55+
}
56+
} else { // Create.
57+
err = domainRepo.AddDNSEntry(domainName, domain.DNSEntry{
58+
Name: subDomainName,
59+
Type: provider.setType(),
60+
Content: ip,
61+
Expire: defaultTTL})
62+
if err != nil {
63+
log.Error("failed to add domain:", subDomainName)
64+
return err
65+
}
66+
}
67+
return nil
68+
}
69+
70+
func checkExistence(repo domain.Repository, subdomain, domainName string) (bool, int, error) {
71+
records, err := repo.GetDNSEntries(domainName)
72+
if err == nil {
73+
for _, record := range records {
74+
if record.Name == subdomain {
75+
return true, record.Expire, nil
76+
}
77+
}
78+
}
79+
log.Error("failed to get domain:", domainName)
80+
return false, defaultTTL, err
81+
}
82+
83+
// defaults to A record (ipv4).
84+
func (provider *DNSProvider) setType() string {
85+
if strings.ToUpper(provider.configuration.IPType) == utils.IPV6 {
86+
return utils.IPTypeAAAA
87+
}
88+
return utils.IPTypeA
89+
}

internal/utils/constants.go

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ const (
4343
OVH = "OVH"
4444
// IONOS for IONOS.
4545
IONOS = "IONOS"
46+
// TransIP for TransIP.
47+
TRANSIP = "TransIP"
4648
// IPV4 for IPV4 mode.
4749
IPV4 = "IPV4"
4850
// IPV6 for IPV6 mode.

internal/utils/settings.go

+8
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ func CheckSettings(config *settings.Settings) error {
101101
if config.ConsumerKey == "" {
102102
return errors.New("consumer key cannot be empty")
103103
}
104+
case TRANSIP:
105+
if config.Email == "" {
106+
return errors.New("email cannot be empty")
107+
}
108+
if config.LoginToken == "" {
109+
return errors.New("login token cannot be empty")
110+
}
111+
104112
default:
105113
message := fmt.Sprintf("'%s' is not a supported DNS provider", config.Provider)
106114
return errors.New(message)

0 commit comments

Comments
 (0)