Config Management
Config Management is about taking a configuration described in a formal language, and actually applying it to a Digizuite solution. This includes adding new product configurations, managing "system" users and more.
Use cases
Configuration management should cover the following use cases:
I have an empty DAM and want to add a Media Manager and Sitecore to it
I have done some configuration on a Test environment, and now want to move it to production, however I'm not 100% sure about exactly what I did.
Somebody changed some configuration on an environment manually, however they did not write down what exactly was changed. I want a detailed list of those changes.
A new update of Media Manager is now available, and I want to deploy the required configuration changes, without breaking my existing modifications to the configuration.
As a consultant I want to be able to create predefined configurations that can be used to provide a base for doing custom configuration.
I should be able to manage all things under the System tools area, including things like metafield, members and transcodings.
Concepts
To understand how Digizuite Configuration Management works you need to understand the following concepts:
Resources
A resource
is the most basic thing in config management. Each resource entry corresponds to a single thing
in the Digizuite. It could be a metafield, a user, or simply a single node in a tree metafield.
A resource has many properties, some that can be set as part of configuring the resource, and some that only exists after the resource has been created, but can be used with other resources, to easily link related resources together.
A resource can be created, updated and deleted by the config management system. This allows management of resource consistently between environments.
Resources use the following syntax in the DCL:
resource metafield my_field { name = "My Field" }
Variables
A variable
is a special kind of value, where the value itself is not defined as part of the configuration, but is provided from an external system. This could be things like keys for Azure blob storage, which is something that needs to be different between environments, but where the underlying purpose of having a "blob storage" is the same.
Variables use the following syntax in the DCL:
variable my_variable { type = "string" }
Locals
Locals a temporary values that are used internally to allow easily reusing certain values without repeating them over and over.
Locals use the following syntax in the DCL:
locals { my_first_local = "Foo" my_second_local = 42 }
Layers
To achieve to ability to provide configurations that can be changed and updated independently the config management system provides something called "layers". Each layer is a separately provided configuration. For example the bottom most layer is likely the basic DAM configuration that is required for the DAM to even be able to start. The next layer up might be the Media Manager layer, which provides all the metafields, labels and other configuration Media Manager needs to start.
Layers can generally be separated into two categories, predefined layers, like the DAM and Media Manager layer mentioned above, and customized layers like what each customer would do. The predefined layers are not editable by the customer, while the custom layers are.
Data references
To access something on a previous layer you need to use a data
reference. Data references looks like normal resources, but rather than creating a resource that matches the specified description, it checks all previous layers for a unique resource that looks like that specified definition. Once you have a data reference, you can either use the properties when creating new resource, or use the patch functionality to modify the resource.
Data references use te following syntax in the DCL:
data metafield my_field { Name = "My target field" }
Patches
The change a resource in a previous layer patches can be used. A patch takes a target to update, and the new values the properties should have. It is only necessary to specify the properties that should actually change in the patch definition.
The target for a patch is always a data reference. If resource is defined in the same layer, you can just go edit it directly, and then you do not need a patch.
The syntax for patches are as follows:
patch metafield my_patch { target = data.metafield.my_field Name = "The new name" }
The Digizuite Configuration Language (DCL)
The DCL consists of several individual parts that are brought together to allow for huge flexibility. The language is heavily inspired by HCL from Hashicorp: https://www.terraform.io/docs/language/syntax/configuration.html .
The major building blocks will be shown in this section, and then we will finish with an example of how to attach these things together.
DCL types
The first thing you need to know about the language are the available primitive types:
String
"foo"
, is a string with the valuefoo
. Strings are easy to recognize from the quotes around the value. Both single quote and multi quote strings are allowed, and support the exact same functionality.Int
42
, is an int with the value42
. Ints can be recognized because they are numbers without quotes.Decimal
3.14
, is a decimal with the value3.14
. DCL makes no distinction betweenfloat
anddouble
types.Boolean
true
orfalse
, are booleans with either the valuetrue
or the valuefalse
.
Next are the composite types:
Object, which is a collection of key-value pairs, where each value is one of the types described in this section. Keys are always strings, but without the quotes.
Array, which is an array of values of objects.
Example
A full example of using all these types can look like this:
resource metafield title { string = "My string" int = 42 decimal = 3.14 bool = true object = { my_key = "my value" } array = [ {int = 41}, {int = 42} ] }
Object also accepts the following shorthand syntax, where the =
character is omitted:
resource metafield title { object { my_key = "my value" } }
Functions
DCL allows calling predefined functions to do things that are not directly available in the syntax.
A function call looks like this:
resource metafield title { my_key = my_function("my first argument", "my second argument") }
This calls a function called my_function
and passes in the arguments "my first argument"
and "my second argument"
as the first and second arguments respectively.
Any of the types described in the "DCL Types" section can be passed as arguments to functions.
A set of functions are available out of the box. It is not possible to define custom functions. As an example, the special file
function can be used to refer to binary files, which is used for e.g. the asset
resource type. Furthermore, the special text_file
function allows the user to have e.g. workflow definitions in separate files in a configuration layer, and then reference them when needed.
Both function input and outputs are strongly typed, and will be validated.
References
To make it easier to reuse parts between resources and link resources, DCL has a concept of references. References are a way of using a property of one resource in another resource.
In the simplest form it looks like this:
resource meta_group asset_info { // ... } resource metafield title { name = "title" group_id = resource.meta_group.asset_info.id }
In the above example the group_id
property is set to the same value as the id
property of the "Asset Info" meta group. Accessing nested properties is also possible using additional .
s to dig into the object.
It is possible to use properties that are not known at compile time. Because of this the config management engine is smart enough to create resources in the correct order. In the above case the meta_group
, asset_info
, would be created before the title
metafield
. In the same, but opposite vein, if there are no references, direct or indirect between two resources, they are freely be created in parallel.
References can also be passed as arguments to function, in which case the functions will only be called after the referenced properties are available.
String interpolation
All string types support string interpolation, which looks like this:
resource meta_group asset_info { // ... } resource metafield title { name = "title ${resource.meta_group.asset_info.id}" }
String interpolation allows the user to combine multiple values, and make then dependent on each other.