I'm a fan of CFEngine and use it for the things that many use Puppet or Chef to do. I think the key advantage of some kind of system domain specific language, is it helps document how things are configured. The only way to figure out what's going on in AMIs is mounting their file systems and running diffs to see what changed AMI, to AMI. Having a large number of AMI's can also be a problem in the respect that they proliferate, particularly when you deploy new applications, based on old applications, but slightly different.
On the other hand, if you are using auto-scaling, Chef/Puppet/CFEngine may not be able to finish their work in time if they have to do a lot of work. You have to strike the right balance between what needs to be in the AMI (provisioning) and automation (post-install).
On the other hand, if you are using auto-scaling, Chef/Puppet/CFEngine may not be able to finish their work in time if they have to do a lot of work. You have to strike the right balance between what needs to be in the AMI (provisioning) and automation (post-install).