Each Greengrass V2 component could define its own default configuration which would be used by default.
A deployment, either from cloud or local device, could optionally provide a configuration update instruction to update the configuration for a deployment's target components.
Note: updating configuration is only supported for the target components of a deployment.
The default configuration is defined in the recipe file.
In YAML,
ComponentConfiguration:
DefaultConfiguration:
singleLevelKey: default value of singleLevelKey
nestedObjectkey:
leafKey: default value of /nestedObjectkey/leafKey
listKey:
- 'item1'
- 'item2'
emptyStringKey: ''
emptyListKey: []
emptyMapKey: {}
defaultIsNullKey: null
or in JSON,
{
"ComponentConfiguration": {
"DefaultConfiguration": {
"singleLevelKey": "default value of singleLevelKey",
"nestedObjectkey": {
"leafKey": "default value of /nestedObjectkey/leafKey"
},
"listKey": [
"item1",
"item2"
],
"emptyStringKey": "",
"emptyListKey": [],
"emptyMapKey": {},
"defaultIsNullKey": null
}
}
}
A deployment, either from cloud or local device, could optionally provide a configuration update instruction to update the configuration for a deployment's target components, with the following syntax.
Currently, we only support JSON. We will support YAML as a fast-follow after re:Invent 2020.
{
"RESET": [
"/someOtherKey", "/some/nested/path"
],
"MERGE": {
"singleLevelKey" : "updated value of singleLevelKey",
"newSingleLevelKey": "I was not in the default value and could be added.",
"listKey": ["item3"],
"nestedObjectkey" : {
"leafKey": "updated value of /nestedObjectkey/leafKey",
"newLeafKey": "value of /nestedObjectkey/newLeafKey"
}
}
}
It accepts only one of each RESET
and MERGE
as top-level keys. The configuration will first perform RESET
and then perform MERGE
,
regardless of the order they are given in the JSON Object.
RESET takes a list of String. Each string is a JSON Pointer.
- If a default value doesn't exist at this JSON pointer location, then the key/value pair will be removed entirely.
- If a default value exists at this JSON pointer location, then the value of configuration will be reset to the default value.
Although JSON pointer supports use indexes to locate an element in an Array/List, we don't support using JSON pointer to reset an element in an Array/List for re:Invent 2020. The reason is that resetting an element of an array might cause removal for an index, elements shifting in the array, and other nondeterministic results.
Hence, we've decided to postpone the support for an Array/List to post re:Invent 2020.
An empty JSON pointer string refers to the whole document. To reset the entire configuration, you could simply specify
{
"RESET": [""]
}
Note that if the empty string appears in the list of RESET
, then the rest of pointers in the list will be ignored, and the configuration
will just be reset to the default configuration entirely.
Greengrass V2 will reset the configuration to the default value as is, including null or empty values, for example:
- Default value is an empty List
{"emptyListKey": []}
. The config will be reset to an empty list with JSON pointer/emptyListKey
. - Default value is an empty Map/Object
{"emptyMapKey": {}}
. The config will be reset to an empty map with JSON pointer/emptyMapKey
. - Default value is an empty String
{"emptyStringKey": ""}
. The config will be reset to an empty string with JSON pointer/emptyStringKey
. - Default value is null
{"defaultIsNullKey": null}
. The config will be reset to null with JSON pointer/defaultIsNullKey
.
MERGE
takes a map object, representing the new configuration.
The given object will be merged to the existing configuration object level by level.
At every level, we go over all the key-value pairs in the new config map, and look up the key in the existing configuration:
- If a key already exists, its value will be overwritten by the new configuration value.
- If a key doesn't exist, the key-value pair will be added to the existing configuration. Note: a new key could be added, even it does not exist in the default configuration.
- If a config node has children, it's a 'container' node.
- If a config node has value but not children, it's a 'leaf' node.
- If during a MERGE, a config node changes between 'leaf' and 'container' in type, the old node will be removed and a new one will be created. Subscribers of the old node will be copied over to the new node. Node subscribers will be notified of a 'removed' event, and parent node subscribers will be notified of a 'childRemoved' event.
Similar to removal, list append and insertion-at-index require handling additional complexity of array index changing, elements shifting, and other nondeterministic results.
Hence, we've decided to postpone the support for Array/List appends and insertions to post re:Invent 2020.
However, it's still possible to override the entire list. If you really need to make updates at the element level, think about using a map instead, by giving each element an unique key.
YES. We are providing the flexibility to do so, so that new configurations could be added during deployments.
YES. You can merge empty String, List, or Object/Map.
YES. When reading the merged configuration, you will be able to find the key with value as null
.
YES. The new value will be merged in and overrides the old value. This allows you to potentially change the configuration object's structure. See the following example:
Existing configuration:
{ "myKey": "myValue" }
Config update instruction:
{
"MERGE": {
"myKey": {
"nestedKey1": "myValue"
}
}
}
Result:
{
"myKey": {
"nestedKey1": "myValue"
}
}
If the default value does not exist for that location, you could RESET with the JSON pointer pointing to that location and the value will get removed.
However, if a default value does exist, usually it means the the configuration is used in the component recipe or application logic. Hence removing the config value is very risky. In fact, this is the reason why removal is not supported directly.
If you are sure and really want to remove a config value, you could MERGE in a null
value.