Skip to content

Commit a54afb0

Browse files
authored
feat(rdns): support setting RDNS for Primary IPs (#669)
Previously you could only set the RDNS for Primary IPs if they were attached to a server, through the `server_id` attribute. This now also allows setting the RDNS for Primary IPs directly, even if they are not attached to a server. Closes #668
1 parent 1bf4bae commit a54afb0

File tree

5 files changed

+138
-15
lines changed

5 files changed

+138
-15
lines changed

internal/e2etests/rdns/resource_test.go

+72-7
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ package rdns_test
22

33
import (
44
"fmt"
5-
"testing"
65

7-
"github.com/hetznercloud/terraform-provider-hcloud/internal/e2etests"
8-
"github.com/hetznercloud/terraform-provider-hcloud/internal/loadbalancer"
9-
"github.com/hetznercloud/terraform-provider-hcloud/internal/sshkey"
6+
"testing"
107

8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
119
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1210

11+
"github.com/hetznercloud/hcloud-go/hcloud"
12+
"github.com/hetznercloud/terraform-provider-hcloud/internal/e2etests"
1313
"github.com/hetznercloud/terraform-provider-hcloud/internal/floatingip"
14+
"github.com/hetznercloud/terraform-provider-hcloud/internal/loadbalancer"
15+
"github.com/hetznercloud/terraform-provider-hcloud/internal/primaryip"
1416
"github.com/hetznercloud/terraform-provider-hcloud/internal/rdns"
1517
"github.com/hetznercloud/terraform-provider-hcloud/internal/server"
16-
17-
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
18-
"github.com/hetznercloud/hcloud-go/hcloud"
18+
"github.com/hetznercloud/terraform-provider-hcloud/internal/sshkey"
1919
"github.com/hetznercloud/terraform-provider-hcloud/internal/testsupport"
2020
"github.com/hetznercloud/terraform-provider-hcloud/internal/testtemplate"
2121
)
@@ -97,6 +97,71 @@ func TestRDNSResource_Server(t *testing.T) {
9797
}
9898
}
9999

100+
func TestRDNSResource_PrimaryIP(t *testing.T) {
101+
tests := []struct {
102+
name string
103+
dns string
104+
primaryIPType string
105+
}{
106+
{
107+
name: "primary-ipv6-rdns",
108+
dns: "ipv6.example.hetzner.cloud",
109+
primaryIPType: "ipv6",
110+
},
111+
{
112+
name: "primary-ipv4-rdns",
113+
dns: "ipv4.example.hetzner.cloud",
114+
primaryIPType: "ipv4",
115+
},
116+
}
117+
118+
for _, tt := range tests {
119+
t.Run(tt.name, func(t *testing.T) {
120+
var primaryIP hcloud.PrimaryIP
121+
122+
tmplMan := testtemplate.Manager{}
123+
restPrimaryIP := &primaryip.RData{
124+
Name: tt.name,
125+
Type: tt.primaryIPType,
126+
AssigneeType: "server",
127+
Datacenter: e2etests.TestDataCenter,
128+
}
129+
restPrimaryIP.SetRName(tt.name)
130+
resRDNS := rdns.NewRDataPrimaryIP(t, tt.name, restPrimaryIP.TFID()+".id", restPrimaryIP.TFID()+".ip_address", tt.dns)
131+
132+
// TODO: Debug issues that causes this to fail when running in parallel
133+
resource.Test(t, resource.TestCase{
134+
PreCheck: e2etests.PreCheck(t),
135+
Providers: e2etests.Providers(),
136+
CheckDestroy: testsupport.CheckResourcesDestroyed(primaryip.ResourceType, primaryip.ByID(t, &primaryIP)),
137+
Steps: []resource.TestStep{
138+
{
139+
// Create a new SSH Key using the required values
140+
// only.
141+
Config: tmplMan.Render(t,
142+
"testdata/r/hcloud_primary_ip", restPrimaryIP,
143+
"testdata/r/hcloud_rdns", resRDNS,
144+
),
145+
Check: resource.ComposeTestCheckFunc(
146+
testsupport.CheckResourceExists(restPrimaryIP.TFID(), primaryip.ByID(t, &primaryIP)),
147+
resource.TestCheckResourceAttr(resRDNS.TFID(), "dns_ptr", tt.dns),
148+
),
149+
},
150+
{
151+
// Try to import the newly created RDNS
152+
ResourceName: resRDNS.TFID(),
153+
ImportStateIdFunc: func(state *terraform.State) (string, error) {
154+
return fmt.Sprintf("p-%d-%s", primaryIP.ID, primaryIP.IP.String()), nil
155+
},
156+
ImportState: true,
157+
ImportStateVerify: true,
158+
},
159+
},
160+
})
161+
})
162+
}
163+
}
164+
100165
func TestRDNSResource_FloatingIP(t *testing.T) {
101166
tests := []struct {
102167
name string

internal/rdns/resource_rdns.go

+26-3
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,25 @@ func Resource() *schema.Resource {
3434
Type: schema.TypeInt,
3535
Optional: true,
3636
ForceNew: true,
37-
ExactlyOneOf: []string{"server_id", "floating_ip_id", "load_balancer_id"},
37+
ExactlyOneOf: []string{"server_id", "primary_ip_id", "floating_ip_id", "load_balancer_id"},
38+
},
39+
"primary_ip_id": {
40+
Type: schema.TypeInt,
41+
Optional: true,
42+
ForceNew: true,
43+
ExactlyOneOf: []string{"server_id", "primary_ip_id", "floating_ip_id", "load_balancer_id"},
3844
},
3945
"floating_ip_id": {
4046
Type: schema.TypeInt,
4147
Optional: true,
4248
ForceNew: true,
43-
ExactlyOneOf: []string{"server_id", "floating_ip_id", "load_balancer_id"},
49+
ExactlyOneOf: []string{"server_id", "primary_ip_id", "floating_ip_id", "load_balancer_id"},
4450
},
4551
"load_balancer_id": {
4652
Type: schema.TypeInt,
4753
Optional: true,
4854
ForceNew: true,
49-
ExactlyOneOf: []string{"server_id", "floating_ip_id", "load_balancer_id"},
55+
ExactlyOneOf: []string{"server_id", "primary_ip_id", "floating_ip_id", "load_balancer_id"},
5056
},
5157
"ip_address": {
5258
Type: schema.TypeString,
@@ -82,6 +88,8 @@ func resourceReverseDNSRead(ctx context.Context, d *schema.ResourceData, m inter
8288
switch v := rdns.(type) {
8389
case *hcloud.Server:
8490
d.Set("server_id", v.ID)
91+
case *hcloud.PrimaryIP:
92+
d.Set("primary_ip_id", v.ID)
8593
case *hcloud.FloatingIP:
8694
d.Set("floating_ip_id", v.ID)
8795
case *hcloud.LoadBalancer:
@@ -97,6 +105,7 @@ func resourceReverseDNSRead(ctx context.Context, d *schema.ResourceData, m inter
97105
func resourceReverseDNSCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
98106
c := m.(*hcloud.Client)
99107
serverID, serverOK := d.GetOk("server_id")
108+
primaryIPID, primaryIPOK := d.GetOk("primary_ip_id")
100109
floatingIPID, floatingIPOK := d.GetOk("floating_ip_id")
101110
loadBalancerID, loadBalancerOK := d.GetOk("load_balancer_id")
102111

@@ -114,6 +123,9 @@ func resourceReverseDNSCreate(ctx context.Context, d *schema.ResourceData, m int
114123
case serverOK:
115124
rdns, _, err = c.Server.GetByID(ctx, serverID.(int))
116125
resourceName = "Server"
126+
case primaryIPOK:
127+
rdns, _, err = c.PrimaryIP.GetByID(ctx, primaryIPID.(int))
128+
resourceName = "Primary IP"
117129
case floatingIPOK:
118130
rdns, _, err = c.FloatingIP.GetByID(ctx, floatingIPID.(int))
119131
resourceName = "Floating IP"
@@ -201,6 +213,8 @@ func generateRDNSID(rdns hcloud.RDNSSupporter, ip net.IP) string {
201213
switch v := rdns.(type) {
202214
case *hcloud.Server:
203215
return fmt.Sprintf("s-%d-%s", v.ID, ip)
216+
case *hcloud.PrimaryIP:
217+
return fmt.Sprintf("p-%d-%s", v.ID, ip)
204218
case *hcloud.FloatingIP:
205219
return fmt.Sprintf("f-%d-%s", v.ID, ip)
206220
case *hcloud.LoadBalancer:
@@ -262,6 +276,15 @@ func lookupRDNSID(ctx context.Context, terraformID string, client *hcloud.Client
262276
return nil, nil, InvalidRDNSIDError{terraformID}
263277
}
264278
rdns = srv
279+
case "p":
280+
pip, _, err := client.PrimaryIP.GetByID(ctx, id)
281+
if err != nil {
282+
return nil, nil, err
283+
}
284+
if pip == nil {
285+
return nil, nil, InvalidRDNSIDError{terraformID}
286+
}
287+
rdns = pip
265288
case "f":
266289
fip, _, err := client.FloatingIP.GetByID(ctx, id)
267290
if err != nil {

internal/rdns/testing.go

+12
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type RData struct {
4646
testtemplate.DataCommon
4747

4848
ServerID string
49+
PrimaryIPID string
4950
FloatingIPID string
5051
LoadBalancerID string
5152
IPAddress string
@@ -68,6 +69,17 @@ func NewRDataServer(t *testing.T, rName string, serverID string, ipAddress strin
6869
return r
6970
}
7071

72+
// NewRDataPrimaryIP creates data for a new rdns resource with primary_ip_id.
73+
func NewRDataPrimaryIP(t *testing.T, rName string, primaryIPID string, ipAddress string, dnsPTR string) *RData {
74+
r := &RData{
75+
PrimaryIPID: primaryIPID,
76+
IPAddress: ipAddress,
77+
DNSPTR: dnsPTR,
78+
}
79+
r.SetRName(rName)
80+
return r
81+
}
82+
7183
// NewRDataFloatingIP creates data for a new rdns resource with floating_ip_id.
7284
func NewRDataFloatingIP(t *testing.T, rName string, floatingIPID string, ipAddress string, dnsPTR string) *RData {
7385
r := &RData{

internal/testdata/r/hcloud_rdns.tf.tmpl

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ resource "hcloud_rdns" "{{ .RName }}" {
44
{{- if .ServerID }}
55
server_id = {{ .ServerID }}
66
{{ end }}
7+
{{- if .PrimaryIPID }}
8+
primary_ip_id = {{ .PrimaryIPID }}
9+
{{ end }}
710
{{- if .FloatingIPID }}
811
floating_ip_id = {{ .FloatingIPID }}
912
{{ end }}

website/docs/r/rdns.html.md

+25-5
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ layout: "hcloud"
33
page_title: "Hetzner Cloud: hcloud_rdns"
44
sidebar_current: "docs-hcloud-resource-rdns"
55
description: |-
6-
Provides a Hetzner Cloud Reverse DNS Entry to create, modify and reset reverse dns entries for Hetzner Cloud Servers, Floating IPs or Load Balancers.
6+
Provides a Hetzner Cloud Reverse DNS Entry to create, modify and reset reverse dns entries for Hetzner Cloud Servers, Primary IPs, Floating IPs or Load Balancers.
77
---
88

99
# hcloud_rdns
1010

11-
Provides a Hetzner Cloud Reverse DNS Entry to create, modify and reset reverse dns entries for Hetzner Cloud Servers, Floating IPs or Load Balancers.
11+
Provides a Hetzner Cloud Reverse DNS Entry to create, modify and reset reverse dns entries for Hetzner Cloud Servers, Primary IPs, Floating IPs or Load Balancers.
1212

1313
## Example Usage
1414

@@ -28,6 +28,21 @@ resource "hcloud_rdns" "master" {
2828
}
2929
```
3030

31+
For Primary IPs:
32+
33+
```hcl
34+
resource "hcloud_primary_ip" "primary1" {
35+
datacenter = "nbg1-dc3"
36+
type = "ipv4"
37+
}
38+
39+
resource "hcloud_rdns" "primary1" {
40+
primary_ip_id = hcloud_primary_ip.primary1.id
41+
ip_address = hcloud_primary_ip.primary1.ip_address
42+
dns_ptr = "example.com"
43+
}
44+
```
45+
3146
For Floating IPs:
3247

3348
```hcl
@@ -62,16 +77,18 @@ resource "hcloud_rdns" "load_balancer_master" {
6277

6378
- `dns_ptr` - (Required, string) The DNS address the `ip_address` should resolve to.
6479
- `ip_address` - (Required, string) The IP address that should point to `dns_ptr`.
65-
- `server_id` - (Required, int) The server the `ip_address` belongs to. Specify only one of `server_id`, `floating_ip_id` and `load_balancer_id`.
66-
- `floating_ip_id` - (Required, int) The Floating IP the `ip_address` belongs to. Specify only one of `server_id`, `floating_ip_id` and `load_balancer_id`.
67-
- `load_balancer_id` - (Required, int) The Load Balancer the `ip_address` belongs to. Specify only one of `server_id`, `floating_ip_id` and `load_balancer_id`.
80+
- `server_id` - (Required, int) The server the `ip_address` belongs to. - `server_id` - (Required, int) The server the `ip_address` belongs to. Specify only one of `server_id`, `primary_ip_id`, `floating_ip_id` and `load_balancer_id`.
81+
- `primary_ip_id` - (Required, int) The Primary IP the `ip_address` belongs to. - `server_id` - (Required, int) The server the `ip_address` belongs to. Specify only one of `server_id`, `primary_ip_id`, `floating_ip_id` and `load_balancer_id`.
82+
- `floating_ip_id` - (Required, int) The Floating IP the `ip_address` belongs to. - `server_id` - (Required, int) The server the `ip_address` belongs to. Specify only one of `server_id`, `primary_ip_id`, `floating_ip_id` and `load_balancer_id`.
83+
- `load_balancer_id` - (Required, int) The Load Balancer the `ip_address` belongs to. - `server_id` - (Required, int) The server the `ip_address` belongs to. Specify only one of `server_id`, `primary_ip_id`, `floating_ip_id` and `load_balancer_id`.
6884

6985
## Attributes Reference
7086

7187
- `id` - (int) Unique ID of the Reverse DNS Entry.
7288
- `dns_ptr` - (string) DNS pointer for the IP address.
7389
- `ip_address` - (string) IP address.
7490
- `server_id` - (int) The server the IP address belongs to.
91+
- `primary_ip_id` - (int) The Primary IP the IP address belongs to.
7592
- `floating_ip_id` - (int) The Floating IP the IP address belongs to.
7693
- `load_balancer_id` - (int) The Load Balancer the IP address belongs to.
7794

@@ -84,6 +101,9 @@ Reverse DNS entries can be imported using a compound ID with the following forma
84101
# import reverse dns entry on server with id 123, ip 192.168.100.1
85102
terraform import hcloud_rdns.myrdns s-123-192.168.100.1
86103
104+
# import reverse dns entry on primary ip with id 123, ip 2001:db8::1
105+
terraform import hcloud_rdns.myrdns p-123-2001:db8::1
106+
87107
# import reverse dns entry on floating ip with id 123, ip 2001:db8::1
88108
terraform import hcloud_rdns.myrdns f-123-2001:db8::1
89109

0 commit comments

Comments
 (0)