Skip to content

Add DefaultReadFiltered, filter ip_dhcp_server_lease resource reads based on dynamic field #794

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

kahlstrm
Copy link

The setup that I have currently is that I have a bootstrap script that sets up the devices in a state where I can run terraform apply against that, regardless of the existing state in terraform. This is admittedly a bit cursed but bear with me.

The problem I'm facing is with dhcp leases, where MikroTik seemingly doesn't separate between dynamic leases and static ones in their IDs.
This then causes a problem where the ID that terraform state has for the static lease is currently a dynamic lease, which results in Error: PATCH 'https://10.1.1.2/rest/ip/dhcp-server/lease/*1' returned response code: 400, message: 'Bad Request', details: 'failure: can not change dynamic lease'.

As dynamic leases can not be changed anyways, probably would be okay to add filtering on the read of routeros_ip_dhcp_server_lease that filters out dynamic leases with dynamic=no.

Did this with adding a DefaultReadFiltered as well as two more underlying functions to mimic DefaultRead, and then calling it routeros/resource_ip_dhcp_server_lease.go.

Tested this at least locally and it works for my use case and doesn't seem to cause any weirdness.

Please let me know if this makes any sense, I'm new to terraform providers so there's also that.

@kahlstrm kahlstrm requested a review from a team as a code owner July 28, 2025 07:58
@kahlstrm kahlstrm changed the title fix(ip_dhcp_server_lease): add dynamic field as an identity check Add DefaultReadFiltered, filter ip_dhcp_server_lease resource reads based on dynamic field Jul 28, 2025
@vaerh
Copy link
Collaborator

vaerh commented Jul 28, 2025

Not bad:)
Please tell me what is the use case when static lease is not static?
Are you importing existing resources?

@kahlstrm
Copy link
Author

Not bad:) Please tell me what is the use case when static lease is not static? Are you importing existing resources?

So my use case is a bit cursed, but here we go:

  • I have previously applied my configuration, and the static lease gets assigned to id *1.
  • I reset my router configuration, removing all of the configured state.
  • Before I have time to do terraform apply, a different DHCP server gets a lease request from a different client, and that lease is assigned the ID of *1.
  • After when I run terraform plan I get:
  # routeros_ip_dhcp_server_lease.static_lease will be updated in-place
  ~ resource "routeros_ip_dhcp_server_lease" "static_lease" {
      ~ address            = "10.10.10.254" -> "10.1.1.11"
      - client_id          = "foo" -> null
        id                 = "*1"
      ~ mac_address        = (sensitive value)
      ~ server             = "dhcp1" -> "dhcp2"
        # (16 unchanged attributes hidden)
    }
  • And applying this fails because of failure: can not change dynamic lease.

Does this make sense? Admittedly, it is not entirely "correct" to try to run terraform plan against these kinds of things, but I don't think this change hurts anyone either, given that all DHCP leases with dynamic=yes are immutable.

@vaerh
Copy link
Collaborator

vaerh commented Jul 31, 2025

I would like to look into your case in more detail. It seems to me that this should not be happening for the following reason: Mikrotik increases the counter-identifier when creating a new resource, so the case of identifier reuse can only occur after resetting the device (possibly after deleting resources and rebooting).
It also seems to me that the sequence of actions was incorrect: you need to do apply -destroy, and only then reset the router. This is again one of the incorrect cases when TF resources are managed from within and outside of it.

It is also strictly forbidden to manipulate resources based on whether they are dynamic or not, since TF will not contain an accurate view of the managed resource and, in this case, it will not be possible to ensure its lifecycle.
Ideally, all manipulations with static records should be performed only through TF, and it will be able to find the necessary record based on the MT identifier and do something with it.

@kahlstrm
Copy link
Author

I would like to look into your case in more detail. It seems to me that this should not be happening for the following reason: Mikrotik increases the counter-identifier when creating a new resource, so the case of identifier reuse can only occur after resetting the device (possibly after deleting resources and rebooting). It also seems to me that the sequence of actions was incorrect: you need to do apply -destroy, and only then reset the router. This is again one of the incorrect cases when TF resources are managed from within and outside of it.

It is also strictly forbidden to manipulate resources based on whether they are dynamic or not, since TF will not contain an accurate view of the managed resource and, in this case, it will not be possible to ensure its lifecycle. Ideally, all manipulations with static records should be performed only through TF, and it will be able to find the necessary record based on the MT identifier and do something with it.

Yes, fair enough I guess that I should be doing terraform destroy first before running the device resets, as this case would be a non-issue then. Perhaps I should just do that instead 😄

@vaerh
Copy link
Collaborator

vaerh commented Jul 31, 2025

This question is for Terraform ;)
I think everything else should work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants