I'm running both chef and puppet in production, so I will add my (slightly cynic) comparison here:

When comparing Chef to puppet then Chef comes out as the pragmatist. Once up and running most common every-day tasks are less painful in chef. Apart from that its main advantage over puppet (to me) is that it allows to semi-sanely manage transient hosts (cloud/EC2) that enter/exit a cluster ad hoc. Puppet can also do that in theory, in practice you'd rather want to fork your eyes out with a spoon.

However, the pragmatism comes at a price: The chef-implementation is an absolute and unmitigated disaster.

You'll spend quite a bit of quality time initially to get the six dozen components to play ball and to fix up basics that shouldn't need fixing (i.e. you'll want to ensure that everything is under version control and not just the parts that chef deems worth versioning).

Over the first couple months you'll also see the odd server-crash while you figure out the peculiarities of your particular installation. Chef is very heavy on dependencies and the exact software-versions depend on when and how you install (pkgs vs source-code).

However, once you're over that hump and if you're not too worried about standing on the shoulders of 'a one-eyed amongst the blind' then the whole cookbooks/roles/runlists arrangement is quite comfortable to work with.

Just don't expect features like dry-run, real idempotency or clean dependency tracking that some would consider "basic" for such a tool. Also don't expect a security-model at all; to my knowledge all hosts that are authorized to talk to a chef-server can see all cookbooks and databags on that server.

If you care a lot about those latter minor quibbles then perhaps Puppet might be more your thing.

Puppet is conceptually much cleaner (night/day difference), which sadly and ironically is also its biggest drawback; they took it too far. Puppet made a bad decision early on by inventing their own language. This decision will be your personal ball on a chain for the lifetime of your puppet deployment.

But, is it really that bad?
Well. Yes.

After the initial (steep) learning curve there's only a small plateau of reward before you begin to run into the more subtle issues. The most commonly heard complaints about the language are the ass-backwards class/variable-inheritance and the blurry (and effectively undocumented) divide between what should go into the manifests (sorta like chefs "cookbooks") and what into a storage layer called "extdata" (sorta somewhat like chefs "databags"). But rest assured, there's plenty more, I don't want to spoil it all at once here.

So, yes, you will hate puppet every time you have to make a complex change.

Yet for some it might still be worth it, here's some of my reasons: Once you finally have something up and running puppet feels much more predictable and "solid" than chef. You can actually dry-run and test (most) changes before rolling them out. Puppet will provide meaningful error messages in most situations (unlike the esoteric chef stack-traces). The puppet daemon is just that; one daemon (unlike the conglomerate of moving parts that comprises a chef deployment). Generally speaking there is much less "magic" in puppet than in chef. You will almost always know precisely what went wrong - a pretty important attribute that chef unfortunately doesn't share.

Oh, and no least: the puppet documentation is heads and shoulders above chef (although the latter has improved recently).

So, if you're in the market, good luck making your choice. I'm not making a recommendation here because, quite frankly, I wouldn't recommend either to anyone other than my worst enemy. ;-)