Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit a37b187

Browse files
committed
feat(module): Add Cloudflare DNS module
1 parent 9d036e7 commit a37b187

File tree

10 files changed

+263
-8
lines changed

10 files changed

+263
-8
lines changed

commands/prepare_context.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"github.com/spf13/viper"
55

66
container_docker "github.com/getstackhead/stackhead/modules/container/docker"
7+
dns_cloudflare "github.com/getstackhead/stackhead/modules/dns/cloudflare"
78
plugin_portainer "github.com/getstackhead/stackhead/modules/plugin/portainer"
89
proxy_caddy "github.com/getstackhead/stackhead/modules/proxy/caddy"
910
proxy_nginx "github.com/getstackhead/stackhead/modules/proxy/nginx"
@@ -32,7 +33,8 @@ func PrepareContext(host string, action string, projectDefinition *project.Proje
3233
dnsNames := viper.GetStringMapStringSlice("modules")["dns"]
3334
for _, dnsName := range dnsNames {
3435
switch dnsName {
35-
// todo: add available DNS modules here
36+
case "cloudflare":
37+
system.ContextAddDnsModule(dns_cloudflare.Module{})
3638
}
3739
}
3840

go.mod

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ require (
1313
require (
1414
github.com/Masterminds/sprig/v3 v3.2.2
1515
github.com/blang/semver/v4 v4.0.0
16+
github.com/cloudflare/cloudflare-go v0.54.0
1617
github.com/fatih/structs v1.1.0
1718
github.com/google/go-cmp v0.5.8
1819
github.com/gookit/event v1.0.6
@@ -24,6 +25,7 @@ require (
2425
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
2526
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
2627
gopkg.in/yaml.v3 v3.0.1
28+
robpike.io/filter v0.0.0-20210831053821-dcb4225e6ac8
2729
)
2830

2931
require (
@@ -73,6 +75,7 @@ require (
7375
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
7476
github.com/golang/protobuf v1.5.2 // indirect
7577
github.com/golang/snappy v0.0.4 // indirect
78+
github.com/google/go-querystring v1.1.0 // indirect
7679
github.com/google/uuid v1.3.0 // indirect
7780
github.com/google/wire v0.5.0 // indirect
7881
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
@@ -146,9 +149,9 @@ require (
146149
go4.org/intern v0.0.0-20220617035311-6925f38cc365 // indirect
147150
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect
148151
gocloud.dev v0.25.1-0.20220408200107-09b10f7359f7 // indirect
149-
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 // indirect
152+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
150153
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 // indirect
151-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
154+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
152155
golang.org/x/text v0.3.7 // indirect
153156
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
154157
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect

go.sum

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
236236
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
237237
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
238238
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
239+
github.com/cloudflare/cloudflare-go v0.54.0 h1:sC219lgpWzBHs49w5Pd4yAiDt/rr54C5G05hvo9eDbw=
240+
github.com/cloudflare/cloudflare-go v0.54.0/go.mod h1:cfBrZN1yb+PQfCFqz4PKz5Wnnqa64SlBtlpESPAhk14=
239241
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
240242
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
241243
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -417,6 +419,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
417419
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
418420
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
419421
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
422+
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
423+
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
420424
github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE=
421425
github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk=
422426
github.com/google/go-replayers/httpreplay v1.1.1 h1:H91sIMlt1NZzN7R+/ASswyouLJfW0WLW7fhyUFvDEkY=
@@ -667,8 +671,8 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
667671
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
668672
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
669673
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
670-
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
671674
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
675+
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
672676
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
673677
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
674678
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -801,6 +805,7 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
801805
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
802806
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
803807
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
808+
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
804809
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
805810
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
806811
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
@@ -866,8 +871,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
866871
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
867872
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
868873
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
869-
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
870874
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
875+
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
871876
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
872877
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
873878
github.com/theckman/yacspin v0.8.0 h1:9LA2kUol1/+eH5m/ptlbYCrnCEfLCaX4Xn+5tK/AprI=
@@ -1063,8 +1068,8 @@ golang.org/x/net v0.0.0-20220401154927-543a649e0bdd/go.mod h1:CfG3xpIq0wQ8r1q4Su
10631068
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
10641069
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
10651070
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
1066-
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 h1:lUkvobShwKsOesNfWWlCS5q7fnbG1MEliIzwu886fn8=
1067-
golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
1071+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
1072+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
10681073
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
10691074
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
10701075
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1196,8 +1201,9 @@ golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBc
11961201
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
11971202
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
11981203
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1199-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
12001204
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1205+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
1206+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
12011207
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
12021208
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
12031209
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
@@ -1555,6 +1561,8 @@ k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdi
15551561
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
15561562
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
15571563
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
1564+
robpike.io/filter v0.0.0-20210831053821-dcb4225e6ac8 h1:lwm39gwvSdkVwepWIJM43BTc/1J7f6OCzMNUCox7ozI=
1565+
robpike.io/filter v0.0.0-20210831053821-dcb4225e6ac8/go.mod h1:1GvacT5fu9sizB4SqyrJVJk/CQN2ZN4Z/zld7fYxzLo=
15581566
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
15591567
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
15601568
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

modules/dns/cloudflare/README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Cloudflare DNS module
2+
3+
![Maintained](https://img.shields.io/badge/status-maintained-green)
4+
5+
## About this module
6+
7+
This module allows automatically configuring the DNS settings for a domain.
8+
9+
## Resources
10+
11+
None.
12+
13+
## Configuration
14+
15+
### API Token
16+
17+
Make sure to provide the API token for Cloudflare.
18+
You can generate an API token [in your Cloudflare profile](https://dash.cloudflare.com/profile/api-tokens).
19+
Make sure to grant `write` permissions to DNS on Zone level.
20+
21+
```yaml
22+
modules_config:
23+
cloudflare:
24+
# scoped Cloudflare API token
25+
api_token: MY-API-TOKEN
26+
# switching safemode off will – during project destroy – remove all DNS entries on the domain
27+
disable_safemode: false
28+
```
29+
30+
### Domain setting
31+
32+
You'll also have to define the DNS provider to be used for each domain you want to set up in project definition:
33+
34+
```yaml
35+
domains:
36+
- domain: mydomain.com
37+
dns:
38+
provider: cloudflare
39+
```
40+

modules/dns/cloudflare/deploy.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package dns_cloudflare
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"regexp"
7+
8+
"github.com/cloudflare/cloudflare-go"
9+
"robpike.io/filter"
10+
11+
"github.com/getstackhead/stackhead/project"
12+
"github.com/getstackhead/stackhead/system"
13+
)
14+
15+
func GetDomain(domain string) string {
16+
var re = regexp.MustCompile(`(?P<Sub>.*)\.(?P<Main>.*\..*)`)
17+
match := re.FindStringSubmatch(domain)
18+
return match[re.SubexpIndex("Main")]
19+
}
20+
21+
func GetSubdomain(domain string) string {
22+
var re = regexp.MustCompile(`(?P<Sub>.*)\.(?P<Main>.*\..*)`)
23+
match := re.FindStringSubmatch(domain)
24+
subIndex := re.SubexpIndex("Sub")
25+
if len(match) <= subIndex {
26+
// no subdomain found
27+
return "@"
28+
}
29+
return match[subIndex]
30+
}
31+
32+
func (m Module) Deploy(_modulesSettings interface{}) error {
33+
moduleSettings, err := system.UnpackModuleSettings[ModuleSettings](_modulesSettings)
34+
if err != nil {
35+
return fmt.Errorf("unable to load module settings: " + err.Error())
36+
}
37+
if len(moduleSettings.ApiToken) == 0 {
38+
return fmt.Errorf("missing Cloudflare API token. Supply one in module settings.")
39+
}
40+
// Construct a new API object using a global API key
41+
api, err := cloudflare.NewWithAPIToken(moduleSettings.ApiToken)
42+
if err != nil {
43+
return err
44+
}
45+
46+
ctx := context.Background()
47+
domains := filter.Choose(system.Context.Project.Domains, func(d project.Domains) bool {
48+
return d.DNS.Provider == "cloudflare"
49+
}).([]project.Domains)
50+
51+
proxied := false
52+
for _, domain := range domains {
53+
zoneName := GetDomain(domain.Domain)
54+
zoneId, err := api.ZoneIDByName(zoneName)
55+
if err != nil {
56+
return fmt.Errorf("unable to find Zone ID for name \"" + zoneName + "\": " + err.Error())
57+
}
58+
dnsRecord := constructRecord(domain.Domain)
59+
dnsRecord.Proxied = &proxied
60+
// API scope: dns_records:edit
61+
response, err := api.CreateDNSRecord(ctx, zoneId, dnsRecord)
62+
if err != nil {
63+
return err
64+
}
65+
fmt.Println(response)
66+
}
67+
return nil
68+
}

modules/dns/cloudflare/destroy.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package dns_cloudflare
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/cloudflare/cloudflare-go"
8+
logger "github.com/sirupsen/logrus"
9+
"robpike.io/filter"
10+
11+
"github.com/getstackhead/stackhead/project"
12+
"github.com/getstackhead/stackhead/system"
13+
)
14+
15+
func (m Module) Destroy(_modulesSettings interface{}) error {
16+
moduleSettings, err := system.UnpackModuleSettings[ModuleSettings](_modulesSettings)
17+
if err != nil {
18+
return fmt.Errorf("unable to load module settings: " + err.Error())
19+
}
20+
if len(moduleSettings.ApiToken) == 0 {
21+
return fmt.Errorf("missing Cloudflare API token. Supply one in module settings.")
22+
}
23+
// Construct a new API object using a global API key
24+
api, err := cloudflare.NewWithAPIToken(moduleSettings.ApiToken)
25+
if err != nil {
26+
return err
27+
}
28+
29+
ctx := context.Background()
30+
domains := filter.Choose(system.Context.Project.Domains, func(d project.Domains) bool {
31+
return d.DNS.Provider == "cloudflare"
32+
}).([]project.Domains)
33+
34+
for _, domain := range domains {
35+
zoneName := GetDomain(domain.Domain)
36+
zoneId, err := api.ZoneIDByName(zoneName)
37+
if err != nil {
38+
return fmt.Errorf("unable to find Zone ID for name \"" + zoneName + "\": " + err.Error())
39+
}
40+
dnsRecord := constructRecord(domain.Domain)
41+
dnsRecord.Name = domain.Domain // when looking up the records name is the full domain name
42+
if moduleSettings.DisableSafeMode {
43+
dnsRecord.Content = ""
44+
dnsRecord.Type = ""
45+
}
46+
// API scope: dns_records:read
47+
foundRecords, err := api.DNSRecords(ctx, zoneId, dnsRecord)
48+
if err != nil {
49+
return fmt.Errorf("unable to find DNS record: " + err.Error())
50+
}
51+
if len(foundRecords) == 0 {
52+
if moduleSettings.DisableSafeMode {
53+
logger.Warning("no DNS records were found for name \"" + dnsRecord.Name + "\"")
54+
} else {
55+
logger.Warning("no DNS " + dnsRecord.Type + " record was found for name \"" + dnsRecord.Name + "\" and content \"" + dnsRecord.Content + "\"")
56+
}
57+
return nil
58+
}
59+
if !moduleSettings.DisableSafeMode && len(foundRecords) > 1 {
60+
return fmt.Errorf("more than 1 DNS record was found")
61+
}
62+
63+
// API scope: dns_records:edit
64+
for _, record := range foundRecords {
65+
logger.Info("Removing DNS " + record.Type + " record for name \"" + record.Name + "\" with content \"" + record.Content + "\"")
66+
if err := api.DeleteDNSRecord(ctx, zoneId, record.ID); err != nil {
67+
return err
68+
}
69+
}
70+
}
71+
return nil
72+
}

modules/dns/cloudflare/dns.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package dns_cloudflare
2+
3+
import (
4+
"embed"
5+
6+
"github.com/getstackhead/stackhead/system"
7+
)
8+
9+
type Module struct {
10+
}
11+
12+
// go:embed templates
13+
var templates embed.FS
14+
15+
func (Module) Install(moduleSettings interface{}) error {
16+
// not implemented for modules of type "dns"
17+
return nil
18+
}
19+
20+
func (Module) GetTemplates() *embed.FS {
21+
return &templates
22+
}
23+
24+
func (Module) GetConfig() system.ModuleConfig {
25+
return system.ModuleConfig{
26+
Name: "cloudflare",
27+
Type: "dns",
28+
}
29+
}

modules/dns/cloudflare/init.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package dns_cloudflare
2+
3+
func (Module) Init(moduleSettings interface{}) {
4+
// no implementation
5+
}

modules/dns/cloudflare/record.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package dns_cloudflare
2+
3+
import (
4+
"github.com/cloudflare/cloudflare-go"
5+
"regexp"
6+
7+
"github.com/getstackhead/stackhead/system"
8+
)
9+
10+
func constructRecord(domain string) cloudflare.DNSRecord {
11+
dnsTarget := system.Context.TargetHost.String()
12+
ipv4RegEx := regexp.MustCompile(`^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`)
13+
dnsType := "AAAA"
14+
if len(ipv4RegEx.FindStringIndex(dnsTarget)) > 0 {
15+
dnsType = "A"
16+
}
17+
return cloudflare.DNSRecord{
18+
Type: dnsType,
19+
Name: GetSubdomain(domain),
20+
Content: dnsTarget,
21+
}
22+
}

modules/dns/cloudflare/settings.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package dns_cloudflare
2+
3+
type ModuleSettings struct {
4+
ApiToken string `json:"api_token"`
5+
DisableSafeMode bool `json:"disable_safemode"`
6+
}

0 commit comments

Comments
 (0)