Skip to content

Commit

Permalink
migrate dns_record resource to PluginFramework (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
maksym-nazarenko authored Sep 19, 2023
1 parent d62c67d commit 0b1276c
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 125 deletions.
10 changes: 5 additions & 5 deletions client/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import (
)

type DnsRecord struct {
Id string `mikrotik:".id"`
Name string `mikrotik:"name"`
Ttl types.MikrotikDuration `mikrotik:"ttl"`
Address string `mikrotik:"address"`
Comment string `mikrotik:"comment"`
Id string `mikrotik:".id" codegen:"id,mikrotikID"`
Name string `mikrotik:"name" codegen:"name,terraformID,required"`
Ttl types.MikrotikDuration `mikrotik:"ttl" codegen:"ttl"`
Address string `mikrotik:"address" codegen:"address,required"`
Comment string `mikrotik:"comment" codegen:"comment"`
}

func (d *DnsRecord) ActionToCommand(action Action) string {
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/dns_record.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ resource "mikrotik_dns_record" "record" {

### Read-Only

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

## Import
Import is supported using the following syntax:
Expand Down
1 change: 0 additions & 1 deletion mikrotik/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ func Provider(client *mt.Mikrotik) *schema.Provider {
"mikrotik_bridge_port": resourceBridgePort(),
"mikrotik_bridge_vlan": resourceBridgeVlan(),
"mikrotik_dhcp_server_network": resourceDhcpServerNetwork(),
"mikrotik_dns_record": resourceRecord(),
"mikrotik_interface_list_member": resourceInterfaceListMember(),
"mikrotik_interface_list": resourceInterfaceList(),
"mikrotik_firewall_filter_rule": resourceFirewallFilterRule(),
Expand Down
1 change: 1 addition & 0 deletions mikrotik/provider_framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ func (p *ProviderFramework) Resources(ctx context.Context) []func() resource.Res
NewBridgeResource,
NewDhcpLeaseResource,
NewDhcpServerResource,
NewDnsRecordResource,
NewInterfaceWireguardPeerResource,
NewInterfaceWireguardResource,
NewIpAddressResource,
Expand Down
198 changes: 84 additions & 114 deletions mikrotik/resource_dns_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,147 +2,117 @@ package mikrotik

import (
"context"
"log"

"github.com/ddelnano/terraform-provider-mikrotik/client"
"github.com/ddelnano/terraform-provider-mikrotik/client/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"

tftypes "github.com/hashicorp/terraform-plugin-framework/types"
)

func resourceRecord() *schema.Resource {
return &schema.Resource{
Description: "Creates a DNS record on the MikroTik device.",
type dnsRecord struct {
client *client.Mikrotik
}

CreateContext: resourceServerCreate,
ReadContext: resourceServerRead,
UpdateContext: resourceServerUpdate,
DeleteContext: resourceServerDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
// Ensure the implementation satisfies the expected interfaces.
var (
_ resource.Resource = &dnsRecord{}
_ resource.ResourceWithConfigure = &dnsRecord{}
_ resource.ResourceWithImportState = &dnsRecord{}
)

// NewDnsRecordResource is a helper function to simplify the provider implementation.
func NewDnsRecordResource() resource.Resource {
return &dnsRecord{}
}

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
func (r *dnsRecord) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

r.client = req.ProviderData.(*client.Mikrotik)
}

// Metadata returns the resource type name.
func (r *dnsRecord) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_dns_record"
}

// Schema defines the schema for the resource.
func (s *dnsRecord) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Description: "Creates a DNS record on the MikroTik device.",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
Description: "Unique ID of this resource.",
},
"name": schema.StringAttribute{
Required: true,
Description: "The name of the DNS hostname to be created.",
},
"address": {
Type: schema.TypeString,
"ttl": schema.Int64Attribute{
Optional: true,
Computed: true,
Description: "The ttl of the DNS record.",
},
"address": schema.StringAttribute{
Required: true,
Description: "The A record to be returend from the DNS hostname.",
},
"comment": {
Type: schema.TypeString,
Optional: true,
Description: "The comment text associated with the DNS record.",
},
"ttl": {
Type: schema.TypeInt,
"comment": schema.StringAttribute{
Optional: true,
Computed: true,
Description: "The ttl of the DNS record.",
Description: "The comment text associated with the DNS record.",
},
},
}
}

func resourceServerCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
record := prepareDnsRecord(d)

c := m.(*client.Mikrotik)

dnsRecord, err := c.AddDnsRecord(record)
if err != nil {
return diag.FromErr(err)
}

return recordToData(dnsRecord, d)
// Create creates the resource and sets the initial Terraform state.
func (r *dnsRecord) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var terraformModel dnsRecordModel
var mikrotikModel client.DnsRecord
GenericCreateResource(&terraformModel, &mikrotikModel, r.client)(ctx, req, resp)
}

func resourceServerRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(*client.Mikrotik)

record, err := c.FindDnsRecord(d.Id())

if client.IsNotFoundError(err) {
d.SetId("")
return nil
}
if err != nil {
return diag.FromErr(err)
}

return recordToData(record, d)
// Read refreshes the Terraform state with the latest data.
func (r *dnsRecord) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var terraformModel dnsRecordModel
var mikrotikModel client.DnsRecord
GenericReadResource(&terraformModel, &mikrotikModel, r.client)(ctx, req, resp)
}

func resourceServerUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(*client.Mikrotik)

currentRecord, err := c.FindDnsRecord(d.Id())
record := prepareDnsRecord(d)
record.Id = currentRecord.Id

if err != nil {
return diag.FromErr(err)
}

log.Printf("[DEBUG] About to update dns record with %v", record)
dnsRecord, err := c.UpdateDnsRecord(record)
if err != nil {
return diag.FromErr(err)
}

return recordToData(dnsRecord, d)
// Update updates the resource and sets the updated Terraform state on success.
func (r *dnsRecord) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var terraformModel dnsRecordModel
var mikrotikModel client.DnsRecord
GenericUpdateResource(&terraformModel, &mikrotikModel, r.client)(ctx, req, resp)
}

func resourceServerDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
name := d.Id()

c := m.(*client.Mikrotik)

record, err := c.FindDnsRecord(name)

if err != nil {
return diag.FromErr(err)
}
err = c.DeleteDnsRecord(record.Id)

if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
// Delete deletes the resource and removes the Terraform state on success.
func (r *dnsRecord) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var terraformModel dnsRecordModel
var mikrotikModel client.DnsRecord
GenericDeleteResource(&terraformModel, &mikrotikModel, r.client)(ctx, req, resp)
}

func recordToData(record *client.DnsRecord, d *schema.ResourceData) diag.Diagnostics {
values := map[string]interface{}{
"name": record.Name,
"address": record.Address,
"ttl": record.Ttl,
}

d.SetId(record.Name)

var diags diag.Diagnostics

for key, value := range values {
if err := d.Set(key, value); err != nil {
diags = append(diags, diag.Errorf("failed to set %s: %v", key, err)...)
}
}

return diags
func (r *dnsRecord) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
// Retrieve import ID and save to id attribute
resource.ImportStatePassthroughID(ctx, path.Root("name"), req, resp)
}

func prepareDnsRecord(d *schema.ResourceData) *client.DnsRecord {
dnsRecord := new(client.DnsRecord)

dnsRecord.Name = d.Get("name").(string)
dnsRecord.Ttl = types.MikrotikDuration(d.Get("ttl").(int))
dnsRecord.Address = d.Get("address").(string)
dnsRecord.Comment = d.Get("comment").(string)

return dnsRecord
type dnsRecordModel struct {
Id tftypes.String `tfsdk:"id"`
Name tftypes.String `tfsdk:"name"`
Ttl tftypes.Int64 `tfsdk:"ttl"`
Address tftypes.String `tfsdk:"address"`
Comment tftypes.String `tfsdk:"comment"`
}
9 changes: 5 additions & 4 deletions mikrotik/resource_dns_record_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,9 @@ func TestAccMikrotikDnsRecord_import(t *testing.T) {
resource.TestCheckResourceAttrSet(resourceName, "id")),
},
{
ResourceName: resourceName,
ImportState: true,
ResourceName: resourceName,
ImportStateId: dnsName,
ImportStateVerify: true,
},
},
Expand Down Expand Up @@ -184,7 +185,7 @@ func testAccDnsRecordExists(resourceName string) resource.TestCheckFunc {

c := client.NewClient(client.GetConfigFromEnv())

dnsRecord, err := c.FindDnsRecord(rs.Primary.ID)
dnsRecord, err := c.FindDnsRecord(rs.Primary.Attributes["name"])

if err != nil {
return fmt.Errorf("Unable to get the dns record with error: %v", err)
Expand All @@ -194,7 +195,7 @@ func testAccDnsRecordExists(resourceName string) resource.TestCheckFunc {
return fmt.Errorf("Unable to get the dns record with name: %s", dnsRecord.Name)
}

if dnsRecord.Name == rs.Primary.ID {
if dnsRecord.Name == rs.Primary.Attributes["name"] {
return nil
}
return nil
Expand All @@ -208,7 +209,7 @@ func testAccCheckMikrotikDnsRecordDestroy(s *terraform.State) error {
continue
}

dnsRecord, err := c.FindDnsRecord(rs.Primary.ID)
dnsRecord, err := c.FindDnsRecord(rs.Primary.Attributes["name"])

if !client.IsNotFoundError(err) && err != nil {
return err
Expand Down

0 comments on commit 0b1276c

Please sign in to comment.