-
Notifications
You must be signed in to change notification settings - Fork 25k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow affix settings to specify dependencies #27161
Conversation
We use affix settings to group settings / values under a certain namespace. In some cases like login information for instance a setting is only valid if one or more other settings are present. For instance `x.test.user` is only valid if there is an `x.test.passwd` present and vice versa. This change allows to specify such a dependency to prevent settings updates that leave settings in an inconsistent state.
/cc @javanna |
@s1monw I have been trying this out in #27182. Do I understand correctly that a setting which is dependent on another setting must always be provided in the same request as its dependency? That makes sense for user and password, but in CCS one may want to change the You can reproduce with the following unit test:
|
@javanna I applied your feedback thx |
c700c5e
to
278f416
Compare
@elasticmachine test this please |
@javanna can you take another look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested it out and it works well with the changes from #27182 . I left a few minor comments and a couple of questions. The only minor thing that I wish we could improve, but I am not sure we can, is the error message when you set to null a setting that another one left behind depends on. It may not be clear to users what they have to do to fix that (e.g. set to null the other setting too).
public static final Setting<String> PROXY_HOST_SETTING = Setting.affixKeySetting(PREFIX, "proxy.host", | ||
(key) -> Setting.simpleString(key, Property.NodeScope)); | ||
public static final Setting<String> PROXY_HOST_SETTING = Setting.affixKeySetting("azure.client.", "proxy.host", | ||
(key) -> Setting.simpleString(key, Property.NodeScope), KEY_SETTING, ACCOUNT_SETTING, KEY_SETTING); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess KEY_SETTING shouldn't be repeated twice?
public static final Setting<Integer> PROXY_PORT_SETTING = Setting.affixKeySetting(PREFIX, "proxy.port", | ||
(key) -> Setting.intSetting(key, 0, 0, 65535, Setting.Property.NodeScope)); | ||
public static final Setting<Integer> PROXY_PORT_SETTING = Setting.affixKeySetting("azure.client.", "proxy.port", | ||
(key) -> Setting.intSetting(key, 0, 0, 65535, Setting.Property.NodeScope), ACCOUNT_SETTING, KEY_SETTING); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wondering, shouldn't it also depend on proxy_host ?
(key) -> new Setting<>(key, "direct", s -> Proxy.Type.valueOf(s.toUpperCase(Locale.ROOT)), Property.NodeScope)); | ||
public static final AffixSetting<Proxy.Type> PROXY_TYPE_SETTING = Setting.affixKeySetting("azure.client.", "proxy.type", | ||
(key) -> new Setting<>(key, "direct", s -> Proxy.Type.valueOf(s.toUpperCase(Locale.ROOT)), Property.NodeScope) | ||
, ACCOUNT_SETTING, KEY_SETTING); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not too familiar with these settings, does proxy_type depend also on proxy_host and proxy_port?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I am not sure about that
|
||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: remove this additional empty line
* Returns distinct namespaces for the given settings | ||
*/ | ||
public Set<String> getNamespaces(Settings settings) { | ||
return settings.keySet().stream().filter((key) -> match(key)).map(key::getNamespace).collect(Collectors.toSet()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: match(key) could be replaced with a method reference this::match
@@ -240,7 +241,9 @@ public ClusterState execute(ClusterState currentState) { | |||
if (preserveExisting) { | |||
indexSettings.put(indexMetaData.getSettings()); | |||
} | |||
metaDataBuilder.put(IndexMetaData.builder(indexMetaData).settings(indexSettings)); | |||
Settings finalSettings = indexSettings.build(); | |||
indexScopedSettings.validate(finalSettings.filter(k -> indexScopedSettings.isPrivateSetting(k) == false), true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: private settings are internal only, hence we want to get them out of the validation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah
Settings.Builder persistentSettings = Settings.builder(); | ||
persistentSettings.put(currentState.metaData().persistentSettings()); | ||
changed |= clusterSettings.updateDynamicSettings(persistentToApply, persistentSettings, persistentUpdates, "persistent"); | ||
|
||
final ClusterState clusterState; | ||
if (changed) { | ||
Settings transientFinalSettings = transientSettings.build(); | ||
Settings persistentFinalSettings = persistentSettings.build(); | ||
// both transient and persistent settings must be consistent by itself we can't allow dependencies to be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"must be consistent on their own?"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"we can't allow dependencies between the two"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if you have setting A to be transient and then it disappears on a full cluster restart?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure I agree, I was just suggesting to rephrase the comment :)
@@ -276,7 +276,7 @@ private void validate(PutRequest request) { | |||
} | |||
|
|||
try { | |||
indexScopedSettings.validate(request.settings); | |||
indexScopedSettings.validate(request.settings, true); // templates must be consistent with regards to dependecies |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dependencies
metaDataBuilder.put(IndexMetaData.builder(indexMetaData).settings(indexSettings)); | ||
Settings finalSettings = indexSettings.build(); | ||
indexScopedSettings.validate(finalSettings.filter(k -> indexScopedSettings.isPrivateSetting(k) == false), true); | ||
metaDataBuilder.put(IndexMetaData.builder(indexMetaData).settings(finalSettings)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering if this second step wasn't enough, compared to the first validation step that doesn't look at dependencies. Why have the two steps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one happens before we pass on to a clusterstate update task we should validate as soon as we can. but we have to do it here again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, I left one minor request.
@@ -77,7 +77,7 @@ protected void masterOperation(final PutIndexTemplateRequest request, final Clus | |||
} | |||
final Settings.Builder templateSettingsBuilder = Settings.builder(); | |||
templateSettingsBuilder.put(request.settings()).normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX); | |||
indexScopedSettings.validate(templateSettingsBuilder); | |||
indexScopedSettings.validate(templateSettingsBuilder.build(), true); // templates must be consistent with reg. to dependencies |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you expand reg.
? It took me a few seconds to figure out what it meant (regards
) and I do not want to have to do it every time I read this comment?
@@ -41,41 +41,41 @@ | |||
import java.util.Set; | |||
|
|||
public final class AzureStorageSettings { | |||
// prefix for azure client settings | |||
private static final String PREFIX = "azure.client."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why remove the internal constant? Seems like this is just asking for a typo in the future in one setting to cause a storm of problems :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair enough. I can add it back.
We use affix settings to group settings / values under a certain namespace. In some cases like login information for instance a setting is only valid if one or more other settings are present. For instance `x.test.user` is only valid if there is an `x.test.passwd` present and vice versa. This change allows to specify such a dependency to prevent settings updates that leave settings in an inconsistent state.
* es/master: (24 commits) Reduce synchronization on field data cache add json-processor support for non-map json types (#27335) Properly format IndexGraveyard deletion date as date (#27362) Upgrade AWS SDK Jackson Databind to 2.6.7.1 Stop responding to ping requests before master abdication (#27329) [Test] Fix POI version in packaging tests Allow affix settings to specify dependencies (#27161) Tests: Improve size regex in documentation test (#26879) reword comment Remove unnecessary logger creation for doc values field data [Geo] Decouple geojson parse logic from ShapeBuilders [DOCS] Fixed link to docker content Plugins: Add versionless alias to all security policy codebase properties (#26756) [Test] #27342 Fix SearchRequests#testValidate [DOCS] Move X-Pack-specific Docker content (#27333) Fail queries with scroll that explicitely set request_cache (#27342) [Test] Fix S3BlobStoreContainerTests.testNumberOfMultiparts() Set minimum_master_nodes to all nodes for REST tests (#27344) [Tests] Relax allowed delta in extended_stats aggregation (#27171) Remove S3 output stream (#27280) ...
* 6.x: (27 commits) Reduce synchronization on field data cache [Test] #27342 Fix SearchRequests#testValidate Fail queries with scroll that explicitely set request_cache (#27342) add json-processor support for non-map json types (#27335) Upgrade AWS SDK Jackson Databind to 2.6.7.1 Properly format IndexGraveyard deletion date as date (#27362) Stop responding to ping requests before master abdication (#27329) [Test] Fix POI version in packaging tests Added release notes for 6.0.0 Update 6.0.0-beta1.asciidoc Allow affix settings to specify dependencies (#27161) Tests: Improve size regex in documentation test (#26879) reword comment Ensure external refreshes will also refresh internal searcher to minimize segment creation (#27253) Remove unnecessary logger creation for doc values field data [DOCS] Fixed link to docker content Plugins: Add versionless alias to all security policy codebase properties (#26756) [DOCS] Move X-Pack-specific Docker content (#27333) [Test] Fix S3BlobStoreContainerTests.testNumberOfMultiparts() Set minimum_master_nodes to all nodes for REST tests (#27344) ...
We use affix settings to group settings / values under a certain namespace.
In some cases like login information for instance a setting is only valid if
one or more other settings are present. For instance
x.test.user
is only validif there is an
x.test.passwd
present and vice versa. This change allows to specifysuch a dependency to prevent settings updates that leave settings in an inconsistent
state.