Skip to content

Commit

Permalink
tailscale: add dns_split_nameservers resource (#359)
Browse files Browse the repository at this point in the history
Add `resource_dns_split_nameservers` to allow for controlling split DNS
settings for a given tailnet.

Updates tailscale/corp#19483

Signed-off-by: Mario Minardi <mario@tailscale.com>
  • Loading branch information
mpminardi committed Apr 30, 2024
1 parent 9f2ddea commit 79561c1
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 15 deletions.
42 changes: 42 additions & 0 deletions docs/resources/dns_split_nameservers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "tailscale_dns_split_nameservers Resource - terraform-provider-tailscale"
subcategory: ""
description: |-
The dns_split_nameservers resource allows you to configure split DNS nameservers for your Tailscale network. See https://tailscale.com/kb/1054/dns for more information.
---

# tailscale_dns_split_nameservers (Resource)

The dns_split_nameservers resource allows you to configure split DNS nameservers for your Tailscale network. See https://tailscale.com/kb/1054/dns for more information.

## Example Usage

```terraform
resource "tailscale_dns_split_nameservers" "sample_split_nameservers" {
domain = "foo.example.com"
nameservers = ["1.1.1.1"]
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `domain` (String) Domain to configure split DNS for. Requests for this domain will be resolved using the provided nameservers.
- `nameservers` (Set of String) Devices on your network will use these nameservers to resolve DNS names. IPv4 or IPv6 addresses are accepted.

### Read-Only

- `id` (String) The ID of this resource.

## Import

Import is supported using the following syntax:

```shell
# Split DNS nameservers can be imported using the domain name, e.g.
terraform import tailscale_dns_split_nameservers.sample_split_nameservers example.com
```
2 changes: 2 additions & 0 deletions examples/resources/tailscale_dns_split_nameservers/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Split DNS nameservers can be imported using the domain name, e.g.
terraform import tailscale_dns_split_nameservers.sample_split_nameservers example.com
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "tailscale_dns_split_nameservers" "sample_split_nameservers" {
domain = "foo.example.com"

nameservers = ["1.1.1.1"]
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0
github.com/stretchr/testify v1.9.0
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a
github.com/tailscale/tailscale-client-go v1.16.0
github.com/tailscale/tailscale-client-go v1.17.0
golang.org/x/tools v0.20.0
tailscale.com v1.64.2
)
Expand Down Expand Up @@ -79,7 +79,7 @@ require (
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.17.0 // indirect
golang.org/x/oauth2 v0.19.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a h1:SJy1Pu0eH1C29XwJucQo73FrleVK6t4kYz4NVhp34Yw=
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a/go.mod h1:DFSS3NAGHthKo1gTlmEcSBiZrRJXi28rLNd/1udP1c8=
github.com/tailscale/tailscale-client-go v1.16.0 h1:mipLVbha5SAVGZT/h3I5qZMrrGXz0iAw4QWXKDfe0l0=
github.com/tailscale/tailscale-client-go v1.16.0/go.mod h1:v7ssNztaIngJixKoWAgnfhEbzOyRVPI5qT/niBcoI4k=
github.com/tailscale/tailscale-client-go v1.17.0 h1:4ZTsfB2hiiiIcx7prcXapZHO5K+TXB5fTdhGxdKGR88=
github.com/tailscale/tailscale-client-go v1.17.0/go.mod h1:Zxz9AWl4cNX8F+jE7iIeo6Me7dGPXNdCFIoVeovH6eI=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
Expand Down Expand Up @@ -229,8 +229,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down
19 changes: 10 additions & 9 deletions tailscale/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,16 @@ func Provider(options ...ProviderOption) *schema.Provider {
},
},
ResourcesMap: map[string]*schema.Resource{
"tailscale_acl": resourceACL(),
"tailscale_dns_nameservers": resourceDNSNameservers(),
"tailscale_dns_preferences": resourceDNSPreferences(),
"tailscale_dns_search_paths": resourceDNSSearchPaths(),
"tailscale_device_subnet_routes": resourceDeviceSubnetRoutes(),
"tailscale_device_authorization": resourceDeviceAuthorization(),
"tailscale_tailnet_key": resourceTailnetKey(),
"tailscale_device_tags": resourceDeviceTags(),
"tailscale_device_key": resourceDeviceKey(),
"tailscale_acl": resourceACL(),
"tailscale_dns_nameservers": resourceDNSNameservers(),
"tailscale_dns_preferences": resourceDNSPreferences(),
"tailscale_dns_search_paths": resourceDNSSearchPaths(),
"tailscale_dns_split_nameservers": resourceDNSSplitNameservers(),
"tailscale_device_subnet_routes": resourceDeviceSubnetRoutes(),
"tailscale_device_authorization": resourceDeviceAuthorization(),
"tailscale_tailnet_key": resourceTailnetKey(),
"tailscale_device_tags": resourceDeviceTags(),
"tailscale_device_key": resourceDeviceKey(),
},
DataSourcesMap: map[string]*schema.Resource{
"tailscale_device": dataSourceDevice(),
Expand Down
100 changes: 100 additions & 0 deletions tailscale/resource_dns_split_nameservers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package tailscale

import (
"context"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/tailscale/tailscale-client-go/tailscale"
)

func resourceDNSSplitNameservers() *schema.Resource {
return &schema.Resource{
Description: "The dns_split_nameservers resource allows you to configure split DNS nameservers for your Tailscale network. See https://tailscale.com/kb/1054/dns for more information.",
ReadContext: resourceSplitDNSNameserversRead,
CreateContext: resourceSplitDNSNameserversCreate,
UpdateContext: resourceSplitDNSNameserversUpdate,
DeleteContext: resourceSplitDNSNameserversDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Schema: map[string]*schema.Schema{
"domain": {
Type: schema.TypeString,
Description: "Domain to configure split DNS for. Requests for this domain will be resolved using the provided nameservers.",
Required: true,
},
"nameservers": {
Type: schema.TypeSet,
Description: "Devices on your network will use these nameservers to resolve DNS names. IPv4 or IPv6 addresses are accepted.",
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}

func resourceSplitDNSNameserversRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*tailscale.Client)
splitDNS, err := client.SplitDNS(ctx)
if err != nil {
return diagnosticsError(err, "Failed to fetch split DNS configs")
}

nameservers := splitDNS[d.Id()]

if err = d.Set("nameservers", nameservers); err != nil {
return diag.FromErr(err)
}

return nil
}

func resourceSplitDNSNameserversCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*tailscale.Client)
nameserversSet := d.Get("nameservers").(*schema.Set)
domain := d.Get("domain").(string)

nameserversList := nameserversSet.List()

req := make(tailscale.SplitDnsRequest)
var nameservers []string
for _, nameserver := range nameserversList {
nameservers = append(nameservers, nameserver.(string))
}
req[domain] = nameservers

// Return value is not useful to us here, ignore.
if _, err := client.UpdateSplitDNS(ctx, req); err != nil {
return diagnosticsError(err, "Failed to set dns split nameservers")
}

d.SetId(domain)
return nil
}

func resourceSplitDNSNameserversUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
if !d.HasChange("nameservers") {
return resourceSplitDNSNameserversRead(ctx, d, m)
}

return resourceSplitDNSNameserversCreate(ctx, d, m)
}

func resourceSplitDNSNameserversDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*tailscale.Client)
domain := d.Get("domain").(string)

req := make(tailscale.SplitDnsRequest)
req[domain] = []string{}

// Return value is not useful to us here, ignore.
if _, err := client.UpdateSplitDNS(ctx, req); err != nil {
return diagnosticsError(err, "Failed to set dns split nameservers")
}

return nil
}
29 changes: 29 additions & 0 deletions tailscale/resource_dns_split_nameservers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package tailscale_test

import (
"net/http"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

const testSplitNameservers = `
resource "tailscale_dns_split_nameservers" "test_nameservers" {
domain = "example.com"
nameservers = ["1.2.3.4", "4.5.6.7"]
}`

func TestProvider_TailscaleSplitDNSNameservers(t *testing.T) {
resource.Test(t, resource.TestCase{
IsUnitTest: true,
PreCheck: func() {
testServer.ResponseCode = http.StatusOK
testServer.ResponseBody = nil
},
ProviderFactories: testProviderFactories(t),
Steps: []resource.TestStep{
testResourceCreated("tailscale_dns_split_nameservers.test_nameservers", testSplitNameservers),
testResourceDestroyed("tailscale_dns_split_nameservers.test_nameservers", testSplitNameservers),
},
})
}

0 comments on commit 79561c1

Please sign in to comment.