Idempotency, is one of the core benefits of Puppet in that all managed properties only get synchronized if they do not match their declared state in the manifest.
The exec resource type essentially breaks this feature by making Puppet code procedural instead of declarative in nature.
In order to mitigate against this, if you really MUST use an exec resource type, it is best to put some sort of test in place to determine if the external command really needs to be executed. This will essentially make the Puppet code Idempotent again.
Creates, onlyif, and unless are the only attributes in the exec resource type. They’re there to allow Puppet to verify if the command in the exec resource type really needs to be run. Make sure to use them.
creates – Checks to see if the file/directory specified is present. If it’s present, then the command specified by the exec resource type will not run.
onlyif – Runs a command. If the exit code is 0 (Successful), then the exec resource type will run.
unless – Runs a command. If the exit code is nonzero (Unsuccessful), then the exec resource type will run.
Additional details can be found in the Puppet Documentation: