This blog post is a part of this blog post series:
- Puppet types and providers development part 1: creating the type
- Puppet types and providers development part 2: creating a resource
- Puppet types and providers development part 3: on resource uniqueness
- Puppet types and providers development part 4: caching resource properties to improve performance
- Puppet types and providers development part 5: self.instances
- Puppet types and providers development part 6: mysteries of self.prefetch
In the previous blog post we talked about how to create a resource, a LibreNMS service, in the provider implementation. This blog post will talk about identifying a resource that is being managed. This is a requirement for modifying existing resources.
Modifying existing resources can actually be more tricky than it seems, because you first need to figure out if the resource Puppet is managing already exists on the target system. In many cases the resource type you're managing has an attribute - for example "name", "hostname", "fqdn", "ip" - that is guaranteed to be unique at the target system and works well as the identifier at the Puppet end. This is the case, for example with files (fully-qualified path), packages (name of the package) and in our particular case, LibreNMS devices (hostname).
However, this does not hold true for many things, such as LibreNMS services. As mentioned previously LibreNMS is fine with having multiple services with the exact same properties. It simply uses a different, numeric service_id property to distinguish between them. This is fine for LibreNMS, but bad for us, because we really can't use such internal identifiers in Puppet code if we don't want to end up insane.
Fortunately in the case of librenms_service there was an informal field called "service_desc" that was not used for anything. After a few detours that is what I ended up using as the identifier. There was a gotcha though: as mentioned, LibreNMS does not guarantee uniqueness of the services. And Puppet can only manage uniqueness of the services it manages, not of those that are managed outside of Puppet (e.g. manually). So on any given system there could be several services with the same service_desc. What I ended up doing was to error out duplicates were found. This was the only way to prevent unexpected side-effects like changing multiple services at once, just because they happened to share the same service_desc field.