I know Puppet is a mess. What you say is that you spill lot of exec's into a class? You can avoid that, can't you? If you just declare "resources" and connect them via relationships, then it seems pretty "declarative" to me, i.e. there's no sequence of actions in Puppet DSL and when you run puppet it only does what's necessary. While I find it truly "declarative", I still think Puppet and its ecosystem just suck, for lot of other reasons.
I don't think Ansible even tries to hide the fact that it's just imperative sequence of actions. I wonder where the people saying opposite are coming from. It's just retarded imperative language.