I found this answer very useful in helping me with a similar use case. I wanted to share a simple example of creating an object to iterate over that PatrickWalker refers to ("...build some sort of object that represents the instances.. and loop..."). I hope this may help someone.
Create an attribute with a value which is a JSON string containing an array for each iteration and each array entry containing the parameters for each iteration.
Iterate over this array in a recipe performing an action using the parameters from the JSON string (you can encapsulate re-usable code in a definition or a LWRP).
Simple Example
Creates one or more files with specific names and contents defined in JSON:
Attribute:
default['config'] = '{"files":[{"name":"/tmp/file_1","content":"file contents 1"},{"name":"/tmp/file_2","content":"file contents 2"}]}'
Recipe:
config = JSON.parse("#{node['config']}")
files = config['files']
files.each do |file|
file "#{file['name']}" do
content "#{file['content']}"
end
end
You can extrapolate this simple example into your own use case.