I've used CFengine (long ago) and Ansible (more recently), and the way I remember it, they were similar: Both allow you to express "please ensure that this Debian package is installed" and "please ensure that the file foo contains this line bar".
So, as far as I can tell, in both cases you describe the desired target state of the box, and the tool examines the current state and migrates towards the target state.
I always assumed that Chef and Puppet were similar.
Am I overlooking something?