We use something that's halfway between the second and third
options.
We use standardized namespaces in Hiera that group together logical
sets of data (we use it mostly for distributed app configuration,
but you could easily apply this to system configuration), then we
pull that into our profiles. Not an actual "data class" like your
second option, but a little more complex than your third option.
For example:
define
profiles::vhost (
$sitename = $title,
$parent_config = $title,
) {
$config = merge (
hiera_hash("application::${parent_config}"),
hiera_hash("application::${sitename}")
)
$product = $config['product']
$branch = $config['branch']
$component = $config['component']
$version = $config['version']
$db_user = $config['db_user']
$db_pass = $config['db_pass']
...
}
This lets us share things like database passwords among the various
profiles (vhost, database, etc) and systems that need it, and the
hash merge lets us share common configuration (e.g. log host or
database credentials) among many application sub-components that
might be on different code branches or versions.
This way way have a very, very generic "virtual host" module (or
"database" module or what have you) at the profile level, and our
roles define what namespace(s) we use for configuration (and thus,
what product/component/etc gets deployed, and the data inheritance
structure between them).
This was developed in response to some really specific business
requirements at our site, but it works reasonably well for us.
- Peter