Placeholders

When you create a new configuration unit from scratch and perhaps start from an existing sample, most fields will have reasonable default values. But in some cases, you need to specify a specific value for a field before the config will work and there is no reasonable default.

Common examples of values without reasonable defaults in infrastructures resources are references to network addresses and generated identifiers. It's less common in Kubernetes, but setting the namespace field of resources is an example.

Such values cannot be known in advance so they cannot be included in the config sample that you start with. ConfigHub uses the concept of a special placeholder value to allow authors of config samples to indicate where required information needs to be filled in.

The default placeholder value for strings is "confighubplaceholder" and for integers is 999999999 (9 9s). Placeholder values must be syntactically valid for the data type of the attribute. This enables existing libraries to be able to parse the configuration, and existing linting and schema validation tools to work also. "confighubplaceholder" maximizes compatibility by not including punctuation or capital letters. The "confighub" prefix should ensure that it does not collide with normal configuration values. Placeholder values are not parameters and do not need to be unique. They are just values that can and should be changed.

For example a Kubernetes service account can look like this:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: backend
  namespace: confighubplaceholder

This tells ConfigHub functions multiple things:

  1. This config cannot be applied yet. It is missing some information. This can be enforced using the vet-placeholders function as a trigger.
  2. Specifically, the value of namespace in the resource type v1/ServiceAccount needs to be set because it is not set to a reasonable default value.

Because ConfigHub functions understand the underlying schemas of the resources, functions targeting the namespace field can know that this value is a string and that it's a reference to a resource of type Namespace, much as command-line tools, UIs, and controllers would. Functions can be as specific or as general as the function author intends.

This eliminates:

  1. The need for a special, non-standard schema just to define the parameters. Such a schema would either have to include pretty much all possible fields in a resource type or it would only be applicable to a particular config sample.
  2. The need to insert those parameters. Configuration could originate from a wide variety of sources: imported from a cluster, generated by a tool, generated by AI, etc.
  3. The need for code that reads or writes the configuration to deal with whatever syntax would represent the parameters and to understand the mapping between the parameters and the underlying resource attributes. Parameters would just get in the way of tools operating on the configuration.