We know Python, we don't know Ruby, and we have waaaay less than a dozen servers all up, including staging and dev environments. We don't need anything too complex or over-engineered, but we do need something that'll work, is quick to get started with, and is at least better than the mess of fabric scripts we had before. And ideally it should integrate well with what we already have, and scale as far as we need it to.
Ansible works for this very well. Install it on the machine you want to control everything (my laptop, right now), add all your servers to a manifest, hack together some simple playbooks using a very clear YAML-based DSL, and...you're done. It works via SSL, so no crazy issues with certificates, no complicated server infrastructure, nothing to install on the clients. The barriers to entry are vastly lower than they are for Chef or Puppet; even Chef Solo is kind of overkill. And being in Python is nice; I can hack on a Ansible module if I need to. People love the fact that Chef cookbooks are "just Ruby!" but if you don't know Ruby that's not a good thing; it's much easier to learn Ansible's DSL than Ruby.
At the moment we're using DO, so the process right now is to log in to DOs control panel, create a new droplet, add the IP address to the Ansible inventory, and then hit go, and Ansible will configure everything magically.
Deployment we're still ironing the kinks out of. We're using Dokku for one part of our stack, which is working...okay. Another part is using an Ansible playbook to grab a custom docker image and deploy it, which is a bit nicer. I'm still trying to decide how useful a role Docker is playing; I know it's the new hotness but it's not 100% clear to me that cloning a git repo locally, building docker image, pushing it to a docker repo, pulling it back out of a docker repo on a remote server, and firing it up is that much better than just, you know, cloning a git repo and building the app.
Anyhow, out of Chef, Puppet, Salt, Ansible, etc. we're using Ansible 'cause it solves our problems quickly and easily. If you've ever growled to yourself "christ, I could write a shell script to solve this so easily, why is this HARD?!", well, with Ansible it's not hard, but it still solves stuff you could never do with shell scripts or Fabric.
With dotCloud though, deployments don't have any of that nonsense. Well, I suppose it does, but it was all part of the process. A simple `dotcloud push .` in a directory would run a script that 1) checked to see what servers and services (mysql, postgres, python, nginx, etc.) needed to be pushed to, 2) synced the code up to the server (can't remember if it was scp or rsync -- I think scp), 3) run migrations, 4) pip install requirements.txt.
My own process had a script in front of that to ensure that pushes came from commits, and I also had post-commit hooks that ran other tasks, but the act of deploying code to a dotCloud instance (which is essentially a Docker container) was never more complicated than `dotcloud push .`