Skip to content

Commit

Permalink
Add details about how the dynamic configuration update REST API works…
Browse files Browse the repository at this point in the history
… [DEX-115] (#1121)

* Added a section detailing how the dynamic configuration update REST API works with some examples.

Co-authored-by: Oliver Howell <[email protected]>
  • Loading branch information
ihsandemir and oliverhowell authored Jun 6, 2024
1 parent 807c92f commit 098628c
Showing 1 changed file with 197 additions and 0 deletions.
197 changes: 197 additions & 0 deletions docs/modules/maintain-cluster/pages/enterprise-rest-api.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -474,3 +474,200 @@ curl -X 'DELETE' \
"message": "CP Subsystem is not enabled!"
}
----

== Dynamic Configuration Update REST Endpoint
You can use the `/hazelcast/rest/api/v1/config/update` REST endpoint to change dynamic server configurations (for more info, see xref:configuration:dynamic-config.adoc[Dynamic Configuration for Members]). With dynamic configuration you can change existing configurations dynamically, as well as add new configurations for Hazelcast data structures.

The endpoint requires that you send a XML/YAML server configuration file with the changes required. The response will be two lists in JSON format. The first list includes the newly added configuration among the configurations sent to the server. The second list includes ignored configurations which were in the sent configuration list but could not be applied at the server (examples of these could include static rather than dynamic configurations, which can not therefore be applied dynamically, or duplicate configurations already added).

Whether a dynamic configuration can be applied or not depends on the request. For some updates, it is allowed to change configuration parameters of an existing configuration while for some others you are not allowed to change the configuration. Please see the xref:configuration:dynamic-config.adoc[Dynamic Configuration for Members] section on details about which configuration parameters can be changed dynamically and which can not be changed.

Let's walk through some example requests and responses.

=== Add New MapConfig Using XML Configuration
Here is an example POST request for adding a new `MapConfig` for my-map:

[source,shell]
----
curl -X 'POST' \
'http://localhost:8443/hazelcast/rest/api/v1/config/update' \
-H 'Content-Type: text/plain' \
-d '
<hazelcast xmlns="http://www.hazelcast.com/schema/config">
<map name="my-map">
<in-memory-format>BINARY</in-memory-format>
<statistics-enabled>true</statistics-enabled>
<backup-count>2</backup-count>
</map>
</hazelcast>
'
----

This request creates a configuration for a new map named `my-map`. The in-memory format is set to `BINARY`, while statistics are enabled and the backup count is set to `2`.

In response to this request we should receive a response body such as:

[source,json]
----
{
"addedConfigs": [
{
"sectionName": "map",
"configName": "my-map"
}
],
"ignoredConfigs": []
}
----
As the response indicates, a new map config is added to the `map` section with the name `my-map` and the requested dynamic configurations are applied.

=== Add New MapConfig Using YAML Configuration
Here is an example POST request for adding a new `MapConfig` for my-map-yaml using the YAML configuration:

[source,shell]
----
curl -X 'POST' \
'http://localhost:49567/hazelcast/rest/api/v1/cluster/config/update' \
-H 'accept: application/json' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6IltcImFkbWluXCJdIiwiaWF0IjoxNzE3NTk3MDM1LCJleHAiOjE3MTc1OTc5MzV9.pYtBEvBy2KxrRfFOMSK3k9kS37SayEPCSEcYJlMpHMc' \
-H 'Content-Type: application/json' \
-d 'hazelcast:
map:
my-map-yaml:
in-memory-format: BINARY
statistics-enabled: true
backup-count: 2'
----

We send a request to create a new config for the new map to be created named `my-map-yaml`. The in-memory format is set to BINARY while the statistics is enabled and the backup count is set to 2.

When we send this request we receive the response body similar to this:

[source,json]
----
{
"addedConfigs": [
{
"sectionName": "map",
"configName": "my-map-yaml"
}
],
"ignoredConfigs": []
}
----
As you can observe from the response, a new map config is added for map with name my-map-yaml and all the requested dynamic configurations are applied.

=== Add New Conflicting MapConfig For An Existing Map
If you like to add the config with the same map name and a different configuration, then you get response code 400 meaning an invalid configuration is provided since you can not change an existing map configuration. Let's try this:
[source,shell]
----
curl -X 'POST' \
'http://localhost:8443/hazelcast/rest/api/v1/config/update' \
-H 'Content-Type: text/plain' \
-d '
<hazelcast xmlns="http://www.hazelcast.com/schema/config">
<map name="my-map">
<statistics-enabled>false</statistics-enabled>
</map>
</hazelcast>
'
----
The response has a `statusCode` of 400, and the error message adds further detail:
[source,json]
----
{
"statusCode": 400,
"message": "Cannot add a dynamic configuration 'MapConfig{name='my-map', inMemoryFormat='BINARY', metadataPolicy=CREATE_ON_UPDATE, backupCount=1, asyncBackupCount=0, timeToLiveSeconds=0, maxIdleSeconds=0, readBackupData=false, evictionConfig=EvictionConfig{size=2147483647, maxSizePolicy=PER_NODE, evictionPolicy=NONE, comparatorClassName=null, comparator=null}, merkleTree=MerkleTreeConfig{enabled=null, depth=10}, eventJournal=EventJournalConfig{enabled=false, capacity=10000, timeToLiveSeconds=0}, hotRestart=HotRestartConfig{enabled=false, fsync=false}, dataPersistenceConfig=DataPersistenceConfig{enabled=false, fsync=false}, nearCacheConfig=null, mapStoreConfig=MapStoreConfig{enabled=false, className='null', factoryClassName='null', writeDelaySeconds=0, writeBatchSize=1, implementation=null, factoryImplementation=null, properties={}, initialLoadMode=LAZY, writeCoalescing=true, offload=true}, mergePolicyConfig=MergePolicyConfig{policy='com.hazelcast.spi.merge.PutIfAbsentMergePolicy', batchSize=100}, wanReplicationRef=null, entryListenerConfigs=null, indexConfigs=null, attributeConfigs=null, splitBrainProtectionName=null, queryCacheConfigs=null, cacheDeserializedValues=INDEX_ONLY, statisticsEnabled=false, entryStatsEnabled=false, tieredStoreConfig=TieredStoreConfig{enabled=false, memoryTierConfig=MemoryTierConfig{capacity=256 MEGABYTES}, diskTierConfig=DiskTierConfig{enabled=false, deviceName='default-tiered-store-device'}}, partitioningAttributeConfigs=null, userCodeNamespace=null}' as there is already a conflicting configuration 'MapConfig{name='my-map', inMemoryFormat='BINARY', metadataPolicy=CREATE_ON_UPDATE, backupCount=2, asyncBackupCount=0, timeToLiveSeconds=0, maxIdleSeconds=0, readBackupData=false, evictionConfig=EvictionConfig{size=2147483647, maxSizePolicy=PER_NODE, evictionPolicy=NONE, comparatorClassName=null, comparator=null}, merkleTree=MerkleTreeConfig{enabled=null, depth=10}, eventJournal=EventJournalConfig{enabled=false, capacity=10000, timeToLiveSeconds=0}, hotRestart=HotRestartConfig{enabled=false, fsync=false}, dataPersistenceConfig=DataPersistenceConfig{enabled=false, fsync=false}, nearCacheConfig=null, mapStoreConfig=MapStoreConfig{enabled=false, className='null', factoryClassName='null', writeDelaySeconds=0, writeBatchSize=1, implementation=null, factoryImplementation=null, properties={}, initialLoadMode=LAZY, writeCoalescing=true, offload=true}, mergePolicyConfig=MergePolicyConfig{policy='com.hazelcast.spi.merge.PutIfAbsentMergePolicy', batchSize=100}, wanReplicationRef=null, entryListenerConfigs=null, indexConfigs=null, attributeConfigs=null, splitBrainProtectionName=null, queryCacheConfigs=null, cacheDeserializedValues=INDEX_ONLY, statisticsEnabled=true, entryStatsEnabled=false, tieredStoreConfig=TieredStoreConfig{enabled=false, memoryTierConfig=MemoryTierConfig{capacity=256 MEGABYTES}, diskTierConfig=DiskTierConfig{enabled=false, deviceName='default-tiered-store-device'}}, partitioningAttributeConfigs=null, userCodeNamespace=null}'"
}
----
Within the response body you can see the explanation "as there is already a conflicting configuration 'MapConfig{name='my-map'".

=== Add New MapConfig For An Existing Map But With No Configuration Change
As detailed above, you cannot add a map configuration with the same map name. If you send an update request with the same configuration and map name, this request will be ignored as there is no change. Let's look at this as an example:
[source,shell]
----
curl -X 'POST' \
'http://localhost:8443/hazelcast/rest/api/v1/config/update' \
-H 'Content-Type: text/plain' \
-d '
<hazelcast xmlns="http://www.hazelcast.com/schema/config">
<map name="my-map">
<in-memory-format>BINARY</in-memory-format>
<statistics-enabled>true</statistics-enabled>
<backup-count>2</backup-count>
</map>
</hazelcast>
'
----
This request receives an `OK (200)` response code and the following body:
[source,json]
----
{
"addedConfigs": [],
"ignoredConfigs": [
{
"sectionName": "map",
"configName": "my-map"
}
]
}
----
As the response confirms, no configs are added and the provided config is ignored.

=== Add New MapConfig With Duplicate Configs
As you can see, you can not try adding a map config with the same map name. You can send an update request with the same configuration and map name, and you will observe that this update will be ignored since there is no change. Let's try the request again:
[source,shell]
----
curl -X 'POST' \
'http://localhost:8443/hazelcast/rest/api/v1/config/update' \
-H 'Content-Type: text/plain' \
-d '
<hazelcast xmlns="http://www.hazelcast.com/schema/config">
<map name="my-duplicate-map">
<statistics-enabled>true</statistics-enabled>
</map>
<map name="my-duplicate-map">
<statistics-enabled>true</statistics-enabled>
</map>
</hazelcast>
'
----
We receive a response code OK (200) and the following body:
[source,json]
----
{
"addedConfigs": [
{
"sectionName": "map",
"configName": "my-duplicate-map"
}
],
"ignoredConfigs": []
}
----
As you see from the response, only one MapConfig is added since the duplicate one has exactly the same configuration.

=== Try Adding Non-dynamic Static Configuration
You can try to change a static config, for example the `cluster-name` and observe that it is ignored silently. Since it is not a dynamic configuration, it is neither in ignored nor in the added configs list.
An example request:
[source,shell]
----
curl -X 'POST' \
'http://localhost:8443/hazelcast/rest/api/v1/config/update' \
-H 'Content-Type: text/plain' \
-d '
<hazelcast xmlns="http://www.hazelcast.com/schema/config">
<instance-name>newInstanceName</instance-name>
</hazelcast>
'
----
We receive a response code OK (200) and the following body:
[source,json]
----
{
"addedConfigs": [],
"ignoredConfigs": []
}
----

As you can see from the response, the static configuration is ignored but not listed in the ignored configurations list.

0 comments on commit 098628c

Please sign in to comment.