Skip to content

Commit 552dbb4

Browse files
authored
Add support for dhcp.domain
Last resource for the `dhcp` config. This is a bit redundant with the `dhcp.host` stuff. But, it has a purpose. There are times when you need to rebind a host name to an IP address (like when you want to provide a subdomain). And this is where the `dhcp.domain` is useful. It's unclear if there is more to this resource. There doesn't seem to be any documentation on the OpenWrt wiki. There's only two fields in the LuCI UI, so it seems like the whole thing has been implemented. If not, we can always add it later. Branch: joneshf/add-support-for-dhcp-domain Pull-Request: #132
1 parent 654cd1e commit 552dbb4

File tree

9 files changed

+367
-0
lines changed

9 files changed

+367
-0
lines changed

docs/data-sources/dhcp_domain.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "openwrt_dhcp_domain Data Source - openwrt"
4+
subcategory: ""
5+
description: |-
6+
Binds a domain name to an IP address.
7+
---
8+
9+
# openwrt_dhcp_domain (Data Source)
10+
11+
Binds a domain name to an IP address.
12+
13+
## Example Usage
14+
15+
```terraform
16+
data "openwrt_dhcp_domain" "testing" {
17+
id = "testing"
18+
}
19+
```
20+
21+
<!-- schema generated by tfplugindocs -->
22+
## Schema
23+
24+
### Required
25+
26+
- `id` (String) Name of the section. This name is only used when interacting with UCI directly.
27+
28+
### Read-Only
29+
30+
- `ip` (String) The IP address to be used for this domain.
31+
- `name` (String) Hostname to assign.
32+
33+

docs/resources/dhcp_domain.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "openwrt_dhcp_domain Resource - openwrt"
4+
subcategory: ""
5+
description: |-
6+
Binds a domain name to an IP address.
7+
---
8+
9+
# openwrt_dhcp_domain (Resource)
10+
11+
Binds a domain name to an IP address.
12+
13+
## Example Usage
14+
15+
```terraform
16+
resource "openwrt_dhcp_domain" "testing" {
17+
id = "testing"
18+
ip = "192.168.1.50"
19+
name = "testing"
20+
}
21+
```
22+
23+
<!-- schema generated by tfplugindocs -->
24+
## Schema
25+
26+
### Required
27+
28+
- `id` (String) Name of the section. This name is only used when interacting with UCI directly.
29+
- `ip` (String) The IP address to be used for this domain.
30+
- `name` (String) Hostname to assign.
31+
32+
## Import
33+
34+
Import is supported using the following syntax:
35+
36+
```shell
37+
# Find the Terraform id from LuCI's JSON-RPC API.
38+
# One way to find this information is with `curl` and `jq`:
39+
#
40+
# curl \
41+
# --data '{"id": 0, "method": "foreach", "params": ["dhcp", "domain"]}' \
42+
# http://192.168.1.1/cgi-bin/luci/rpc/uci?auth=$AUTH_TOKEN \
43+
# | jq '.result | map({terraformId: .[".name"]})'
44+
#
45+
# This command will output something like:
46+
#
47+
# [
48+
# {
49+
# "terraformId": "cfg123456",
50+
# }
51+
# ]
52+
#
53+
# We'd then use the information to import the appropriate resource:
54+
55+
terraform import openwrt_dhcp_domain.this cfg123456
56+
```
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
data "openwrt_dhcp_domain" "testing" {
2+
id = "testing"
3+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Find the Terraform id from LuCI's JSON-RPC API.
2+
# One way to find this information is with `curl` and `jq`:
3+
#
4+
# curl \
5+
# --data '{"id": 0, "method": "foreach", "params": ["dhcp", "domain"]}' \
6+
# http://192.168.1.1/cgi-bin/luci/rpc/uci?auth=$AUTH_TOKEN \
7+
# | jq '.result | map({terraformId: .[".name"]})'
8+
#
9+
# This command will output something like:
10+
#
11+
# [
12+
# {
13+
# "terraformId": "cfg123456",
14+
# }
15+
# ]
16+
#
17+
# We'd then use the information to import the appropriate resource:
18+
19+
terraform import openwrt_dhcp_domain.this cfg123456
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
resource "openwrt_dhcp_domain" "testing" {
2+
id = "testing"
3+
ip = "192.168.1.50"
4+
name = "testing"
5+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//go:build acceptance.test
2+
3+
package domain_test
4+
5+
import (
6+
"context"
7+
"fmt"
8+
"log"
9+
"os"
10+
"testing"
11+
12+
"github.com/joneshf/terraform-provider-openwrt/internal/acceptancetest"
13+
"github.com/ory/dockertest/v3"
14+
)
15+
16+
var (
17+
dockerPool *dockertest.Pool
18+
)
19+
20+
func TestMain(m *testing.M) {
21+
var (
22+
code int
23+
err error
24+
tearDown func()
25+
)
26+
ctx := context.Background()
27+
tearDown, dockerPool, err = acceptancetest.Setup(ctx)
28+
defer func() {
29+
tearDown()
30+
os.Exit(code)
31+
}()
32+
if err != nil {
33+
fmt.Printf("Problem setting up tests: %s", err)
34+
code = 1
35+
return
36+
}
37+
38+
log.Printf("Running tests")
39+
code = m.Run()
40+
}

openwrt/dhcp/domain/domain.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package domain
2+
3+
import (
4+
"regexp"
5+
6+
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
7+
"github.com/hashicorp/terraform-plugin-framework/datasource"
8+
"github.com/hashicorp/terraform-plugin-framework/resource"
9+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
10+
"github.com/hashicorp/terraform-plugin-framework/types"
11+
"github.com/joneshf/terraform-provider-openwrt/lucirpc"
12+
"github.com/joneshf/terraform-provider-openwrt/openwrt/internal/lucirpcglue"
13+
)
14+
15+
const (
16+
hostnameAttribute = "name"
17+
hostnameAttributeDescription = "Hostname to assign."
18+
hostnameUCIOption = "name"
19+
20+
ipAddressAttribute = "ip"
21+
ipAddressAttributeDescription = "The IP address to be used for this domain."
22+
ipAddressUCIOption = "ip"
23+
24+
schemaDescription = "Binds a domain name to an IP address."
25+
26+
uciConfig = "dhcp"
27+
uciType = "domain"
28+
)
29+
30+
var (
31+
hostnameSchemaAttribute = lucirpcglue.StringSchemaAttribute[model, lucirpc.Options, lucirpc.Options]{
32+
Description: hostnameAttributeDescription,
33+
ReadResponse: lucirpcglue.ReadResponseOptionString(modelSetHostname, hostnameAttribute, hostnameUCIOption),
34+
ResourceExistence: lucirpcglue.Required,
35+
UpsertRequest: lucirpcglue.UpsertRequestOptionString(modelGetHostname, hostnameAttribute, hostnameUCIOption),
36+
}
37+
38+
ipAddressSchemaAttribute = lucirpcglue.StringSchemaAttribute[model, lucirpc.Options, lucirpc.Options]{
39+
Description: ipAddressAttributeDescription,
40+
ReadResponse: lucirpcglue.ReadResponseOptionString(modelSetIPAddress, ipAddressAttribute, ipAddressUCIOption),
41+
ResourceExistence: lucirpcglue.Required,
42+
UpsertRequest: lucirpcglue.UpsertRequestOptionString(modelGetIPAddress, ipAddressAttribute, ipAddressUCIOption),
43+
Validators: []validator.String{
44+
stringvalidator.Any(
45+
stringvalidator.RegexMatches(
46+
regexp.MustCompile("^([[:digit:]]{1,3}.){3}[[:digit:]]{1,3}$"),
47+
`must be a valid IP address (e.g. "192.168.3.1")`,
48+
),
49+
),
50+
},
51+
}
52+
53+
schemaAttributes = map[string]lucirpcglue.SchemaAttribute[model, lucirpc.Options, lucirpc.Options]{
54+
hostnameAttribute: hostnameSchemaAttribute,
55+
ipAddressAttribute: ipAddressSchemaAttribute,
56+
lucirpcglue.IdAttribute: lucirpcglue.IdSchemaAttribute(modelGetId, modelSetId),
57+
}
58+
)
59+
60+
func NewDataSource() datasource.DataSource {
61+
return lucirpcglue.NewDataSource(
62+
modelGetId,
63+
schemaAttributes,
64+
schemaDescription,
65+
uciConfig,
66+
uciType,
67+
)
68+
}
69+
70+
func NewResource() resource.Resource {
71+
return lucirpcglue.NewResource(
72+
modelGetId,
73+
schemaAttributes,
74+
schemaDescription,
75+
uciConfig,
76+
uciType,
77+
)
78+
}
79+
80+
type model struct {
81+
Hostname types.String `tfsdk:"name"`
82+
Id types.String `tfsdk:"id"`
83+
IPAddress types.String `tfsdk:"ip"`
84+
}
85+
86+
func modelGetHostname(m model) types.String { return m.Hostname }
87+
func modelGetId(m model) types.String { return m.Id }
88+
func modelGetIPAddress(m model) types.String { return m.IPAddress }
89+
90+
func modelSetHostname(m *model, value types.String) { m.Hostname = value }
91+
func modelSetId(m *model, value types.String) { m.Id = value }
92+
func modelSetIPAddress(m *model, value types.String) { m.IPAddress = value }
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
//go:build acceptance.test
2+
3+
package domain_test
4+
5+
import (
6+
"context"
7+
"fmt"
8+
"testing"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
11+
"github.com/joneshf/terraform-provider-openwrt/internal/acceptancetest"
12+
"github.com/joneshf/terraform-provider-openwrt/lucirpc"
13+
"gotest.tools/v3/assert"
14+
)
15+
16+
func TestDataSourceAcceptance(t *testing.T) {
17+
ctx := context.Background()
18+
openWrtServer := acceptancetest.RunOpenWrtServer(
19+
ctx,
20+
*dockerPool,
21+
t,
22+
)
23+
client := openWrtServer.LuCIRPCClient(
24+
ctx,
25+
t,
26+
)
27+
providerBlock := openWrtServer.ProviderBlock()
28+
options := lucirpc.Options{
29+
"ip": lucirpc.String("192.168.1.50"),
30+
"name": lucirpc.String("testing"),
31+
}
32+
ok, err := client.CreateSection(ctx, "dhcp", "domain", "testing", options)
33+
assert.NilError(t, err)
34+
assert.Check(t, ok)
35+
36+
readDataSource := resource.TestStep{
37+
Config: fmt.Sprintf(`
38+
%s
39+
40+
data "openwrt_dhcp_domain" "testing" {
41+
id = "testing"
42+
}
43+
`,
44+
providerBlock,
45+
),
46+
Check: resource.ComposeAggregateTestCheckFunc(
47+
resource.TestCheckResourceAttr("data.openwrt_dhcp_domain.testing", "id", "testing"),
48+
resource.TestCheckResourceAttr("data.openwrt_dhcp_domain.testing", "ip", "192.168.1.50"),
49+
resource.TestCheckResourceAttr("data.openwrt_dhcp_domain.testing", "name", "testing"),
50+
),
51+
}
52+
53+
acceptancetest.TerraformSteps(
54+
t,
55+
readDataSource,
56+
)
57+
}
58+
59+
func TestResourceAcceptance(t *testing.T) {
60+
ctx := context.Background()
61+
openWrtServer := acceptancetest.RunOpenWrtServer(
62+
ctx,
63+
*dockerPool,
64+
t,
65+
)
66+
providerBlock := openWrtServer.ProviderBlock()
67+
68+
createAndReadResource := resource.TestStep{
69+
Config: fmt.Sprintf(`
70+
%s
71+
72+
resource "openwrt_dhcp_domain" "testing" {
73+
id = "testing"
74+
ip = "192.168.1.50"
75+
name = "testing"
76+
}
77+
`,
78+
providerBlock,
79+
),
80+
Check: resource.ComposeAggregateTestCheckFunc(
81+
resource.TestCheckResourceAttr("openwrt_dhcp_domain.testing", "id", "testing"),
82+
resource.TestCheckResourceAttr("openwrt_dhcp_domain.testing", "ip", "192.168.1.50"),
83+
resource.TestCheckResourceAttr("openwrt_dhcp_domain.testing", "name", "testing"),
84+
),
85+
}
86+
importValidation := resource.TestStep{
87+
ImportState: true,
88+
ImportStateVerify: true,
89+
ResourceName: "openwrt_dhcp_domain.testing",
90+
}
91+
updateAndReadResource := resource.TestStep{
92+
Config: fmt.Sprintf(`
93+
%s
94+
95+
resource "openwrt_dhcp_domain" "testing" {
96+
id = "testing"
97+
ip = "192.168.1.51"
98+
name = "testing-1"
99+
}
100+
`,
101+
providerBlock,
102+
),
103+
Check: resource.ComposeAggregateTestCheckFunc(
104+
resource.TestCheckResourceAttr("openwrt_dhcp_domain.testing", "id", "testing"),
105+
resource.TestCheckResourceAttr("openwrt_dhcp_domain.testing", "ip", "192.168.1.51"),
106+
resource.TestCheckResourceAttr("openwrt_dhcp_domain.testing", "name", "testing-1"),
107+
),
108+
}
109+
110+
acceptancetest.TerraformSteps(
111+
t,
112+
createAndReadResource,
113+
importValidation,
114+
updateAndReadResource,
115+
)
116+
}

openwrt/provider.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/joneshf/terraform-provider-openwrt/lucirpc"
1919
"github.com/joneshf/terraform-provider-openwrt/openwrt/dhcp/dhcp"
2020
"github.com/joneshf/terraform-provider-openwrt/openwrt/dhcp/dnsmasq"
21+
"github.com/joneshf/terraform-provider-openwrt/openwrt/dhcp/domain"
2122
"github.com/joneshf/terraform-provider-openwrt/openwrt/dhcp/host"
2223
"github.com/joneshf/terraform-provider-openwrt/openwrt/dhcp/odhcpd"
2324
"github.com/joneshf/terraform-provider-openwrt/openwrt/internal/lucirpcglue"
@@ -164,6 +165,7 @@ func (p *openWrtProvider) DataSources(
164165
device.NewDataSource,
165166
dhcp.NewDataSource,
166167
dnsmasq.NewDataSource,
168+
domain.NewDataSource,
167169
globals.NewDataSource,
168170
host.NewDataSource,
169171
networkinterface.NewDataSource,
@@ -194,6 +196,7 @@ func (p *openWrtProvider) Resources(
194196
device.NewResource,
195197
dhcp.NewResource,
196198
dnsmasq.NewResource,
199+
domain.NewResource,
197200
globals.NewResource,
198201
host.NewResource,
199202
networkinterface.NewResource,

0 commit comments

Comments
 (0)