Puppet does not know what happens in an Exec resource, so it has one foot in and one foot outside of the graph and impairs puppet's ability to define state consistently and enforce idempotency. Because of these, Execs are the least desirable resource type. Think of them as a "break in case of emergency" type resource. Only use them if no other resource will work.
Some alternatives might include:
* Repackage the RPMs to include appropriate post-install scripts, so there is nothing to exec afterward
* Use the correct resource types to achieve the same goal. If the command would modify some file, use a File resource to manage the file's permissions, contents, etc. via puppet.
* If you have multiple commands to run and there is absolutely no way to use other puppet resource types to obtain the same results, then create a script that is pushed down as a Package or File resource, then Exec that file. File+Exec is usually better than a bunch of individual Execs, for both better modeling of state, and your sanity (esp when dealing with escaped strings, any sort of logic between Execs, and to have a logical view of what the Execs are doing).
Again, Execs should generally be your last resort. Find another way when possible!