So a simplified Cloudformation template looks something like this:
{:MyEC2Instance {:Type "AWS::EC2::Instance"
:Properties {:VpcId "vpc-id-here"}}}
This is very basic and probably best validated with clojure.spec. Especially with expound you can get really helpful error messages.
However it get's more complicated when you want to use Cloudformation references to resources declared elsewhere in the template. This is definitely something you want when you make something serious:
{:MyVPC {:Type "AWS::EC2::VPC"
:Properties {:Subnet "..."}}
:MyEC2Instance {:Type "AWS::EC2::Instance"
:Properties {:VpcId {:Ref :MyVPC}}}}
The best thing we can do with clojure.spec is saying that :VpcId can be a string or a Ref map. Ideally my validator would know that we expect a VpcId here which is either a string or a reference to a Cloudformation definition of type "AWS::EC2::VPC". This requires keeping track of references and knowing what type they have.