Skip to content

Commit a6c1916

Browse files
authored
Adding suggest and validate transport actions to node client (#1605)
* adding skip-changelog to get auto added to depandabot PRs Signed-off-by: Amit Galitzky <[email protected]> * adding suggest and validate api to node client Signed-off-by: Amit Galitzky <[email protected]> --------- Signed-off-by: Amit Galitzky <[email protected]>
1 parent 7a0da6d commit a6c1916

17 files changed

+429
-15
lines changed

.github/dependabot.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ updates:
66
interval: "weekly"
77
commit-message:
88
prefix: "dependabot:"
9+
labels:
10+
- "skip-changelog"
911
ignore:
1012
# For all packages, ignore all major versions to minimize breaking issues
1113
- dependency-name: "*"
@@ -15,4 +17,6 @@ updates:
1517
schedule:
1618
interval: "weekly"
1719
commit-message:
18-
prefix: "dependabot:"
20+
prefix: "dependabot:"
21+
labels:
22+
- "skip-changelog"

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
77
### Features
88
### Enhancements
99
- Adds capability to automatically switch to old access-control if model-group is excluded from protected resources setting ([#1569](https://github.com/opensearch-project/anomaly-detection/pull/1569))
10+
- Adding suggest and validate transport actions to node client ([#1605](https://github.com/opensearch-project/anomaly-detection/pull/1605))
1011
- Adding auto create as an optional field on detectors ([#1602](https://github.com/opensearch-project/anomaly-detection/pull/1602))
1112

1213
### Bug Fixes

src/main/java/org/opensearch/ad/client/AnomalyDetectionClient.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
import org.opensearch.common.action.ActionFuture;
1313
import org.opensearch.core.action.ActionListener;
1414
import org.opensearch.timeseries.transport.GetConfigRequest;
15+
import org.opensearch.timeseries.transport.SuggestConfigParamRequest;
16+
import org.opensearch.timeseries.transport.SuggestConfigParamResponse;
17+
import org.opensearch.timeseries.transport.ValidateConfigRequest;
18+
import org.opensearch.timeseries.transport.ValidateConfigResponse;
1519

1620
/**
1721
* A client to provide interfaces for anomaly detection functionality. This will be used by other plugins.
@@ -71,4 +75,39 @@ default ActionFuture<GetAnomalyDetectorResponse> getDetectorProfile(GetConfigReq
7175
*/
7276
void getDetectorProfile(GetConfigRequest profileRequest, ActionListener<GetAnomalyDetectorResponse> listener);
7377

78+
/**
79+
* Validate anomaly detector - refer to https://opensearch.org/docs/latest/observing-your-data/ad/api/#validate-detector
80+
* @param validateRequest request to validate the detector configuration
81+
* @return ActionFuture of ValidateConfigResponse
82+
*/
83+
default ActionFuture<ValidateConfigResponse> validateAnomalyDetector(ValidateConfigRequest validateRequest) {
84+
PlainActionFuture<ValidateConfigResponse> actionFuture = PlainActionFuture.newFuture();
85+
validateAnomalyDetector(validateRequest, actionFuture);
86+
return actionFuture;
87+
}
88+
89+
/**
90+
* Validate anomaly detector - refer to https://opensearch.org/docs/latest/observing-your-data/ad/api/#validate-detector
91+
* @param validateRequest request to validate the detector configuration
92+
* @param listener a listener to be notified of the result
93+
*/
94+
void validateAnomalyDetector(ValidateConfigRequest validateRequest, ActionListener<ValidateConfigResponse> listener);
95+
96+
/**
97+
* Suggest anomaly detector parameters - refer to https://opensearch.org/docs/latest/observing-your-data/ad/api/#suggest-detector
98+
* @param suggestRequest request to suggest detector configuration parameters
99+
* @return ActionFuture of SuggestConfigParamResponse
100+
*/
101+
default ActionFuture<SuggestConfigParamResponse> suggestAnomalyDetector(SuggestConfigParamRequest suggestRequest) {
102+
PlainActionFuture<SuggestConfigParamResponse> actionFuture = PlainActionFuture.newFuture();
103+
suggestAnomalyDetector(suggestRequest, actionFuture);
104+
return actionFuture;
105+
}
106+
107+
/**
108+
* Suggest anomaly detector parameters - refer to https://opensearch.org/docs/latest/observing-your-data/ad/api/#suggest-detector
109+
* @param suggestRequest request to suggest detector configuration parameters
110+
* @param listener a listener to be notified of the result
111+
*/
112+
void suggestAnomalyDetector(SuggestConfigParamRequest suggestRequest, ActionListener<SuggestConfigParamResponse> listener);
74113
}

src/main/java/org/opensearch/ad/client/AnomalyDetectionNodeClient.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,16 @@
1313
import org.opensearch.ad.transport.GetAnomalyDetectorResponse;
1414
import org.opensearch.ad.transport.SearchAnomalyDetectorAction;
1515
import org.opensearch.ad.transport.SearchAnomalyResultAction;
16+
import org.opensearch.ad.transport.SuggestAnomalyDetectorParamAction;
17+
import org.opensearch.ad.transport.ValidateAnomalyDetectorAction;
1618
import org.opensearch.core.action.ActionListener;
1719
import org.opensearch.core.action.ActionResponse;
1820
import org.opensearch.core.common.io.stream.NamedWriteableRegistry;
1921
import org.opensearch.timeseries.transport.GetConfigRequest;
22+
import org.opensearch.timeseries.transport.SuggestConfigParamRequest;
23+
import org.opensearch.timeseries.transport.SuggestConfigParamResponse;
24+
import org.opensearch.timeseries.transport.ValidateConfigRequest;
25+
import org.opensearch.timeseries.transport.ValidateConfigResponse;
2026
import org.opensearch.transport.client.Client;
2127

2228
public class AnomalyDetectionNodeClient implements AnomalyDetectionClient {
@@ -47,6 +53,16 @@ public void getDetectorProfile(GetConfigRequest profileRequest, ActionListener<G
4753
this.client.execute(GetAnomalyDetectorAction.INSTANCE, profileRequest, getAnomalyDetectorResponseActionListener(listener));
4854
}
4955

56+
@Override
57+
public void validateAnomalyDetector(ValidateConfigRequest validateRequest, ActionListener<ValidateConfigResponse> listener) {
58+
this.client.execute(ValidateAnomalyDetectorAction.INSTANCE, validateRequest, validateConfigResponseActionListener(listener));
59+
}
60+
61+
@Override
62+
public void suggestAnomalyDetector(SuggestConfigParamRequest suggestRequest, ActionListener<SuggestConfigParamResponse> listener) {
63+
this.client.execute(SuggestAnomalyDetectorParamAction.INSTANCE, suggestRequest, suggestConfigResponseActionListener(listener));
64+
}
65+
5066
// We need to wrap AD-specific response type listeners around an internal listener, and re-generate the response from a generic
5167
// ActionResponse. This is needed to prevent classloader issues and ClassCastExceptions when executed by other plugins.
5268
// Additionally, we need to inject the configured NamedWriteableRegistry so NamedWriteables (present in sub-fields of
@@ -66,6 +82,31 @@ private ActionListener<GetAnomalyDetectorResponse> getAnomalyDetectorResponseAct
6682
return actionListener;
6783
}
6884

85+
private ActionListener<ValidateConfigResponse> validateConfigResponseActionListener(ActionListener<ValidateConfigResponse> listener) {
86+
ActionListener<ValidateConfigResponse> internalListener = ActionListener.wrap(validateConfigResponse -> {
87+
listener.onResponse(validateConfigResponse);
88+
}, listener::onFailure);
89+
ActionListener<ValidateConfigResponse> actionListener = wrapActionListener(internalListener, actionResponse -> {
90+
ValidateConfigResponse response = ValidateConfigResponse.fromActionResponse(actionResponse, this.namedWriteableRegistry);
91+
return response;
92+
});
93+
return actionListener;
94+
}
95+
96+
private ActionListener<SuggestConfigParamResponse> suggestConfigResponseActionListener(
97+
ActionListener<SuggestConfigParamResponse> listener
98+
) {
99+
ActionListener<SuggestConfigParamResponse> internalListener = ActionListener.wrap(suggestConfigResponse -> {
100+
listener.onResponse(suggestConfigResponse);
101+
}, listener::onFailure);
102+
ActionListener<SuggestConfigParamResponse> actionListener = wrapActionListener(internalListener, actionResponse -> {
103+
SuggestConfigParamResponse response = SuggestConfigParamResponse
104+
.fromActionResponse(actionResponse, this.namedWriteableRegistry);
105+
return response;
106+
});
107+
return actionListener;
108+
}
109+
69110
private <T extends ActionResponse> ActionListener<T> wrapActionListener(
70111
final ActionListener<T> listener,
71112
final Function<ActionResponse, T> recreate

src/main/java/org/opensearch/ad/transport/SuggestAnomalyDetectorParamTransportAction.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.opensearch.common.util.concurrent.ThreadContext;
2424
import org.opensearch.commons.authuser.User;
2525
import org.opensearch.core.action.ActionListener;
26+
import org.opensearch.core.common.io.stream.NamedWriteableRegistry;
2627
import org.opensearch.timeseries.AnalysisType;
2728
import org.opensearch.timeseries.Name;
2829
import org.opensearch.timeseries.constant.CommonMessages;
@@ -50,7 +51,8 @@ public SuggestAnomalyDetectorParamTransportAction(
5051
ADIndexManagement anomalyDetectionIndices,
5152
ActionFilters actionFilters,
5253
TransportService transportService,
53-
SearchFeatureDao searchFeatureDao
54+
SearchFeatureDao searchFeatureDao,
55+
NamedWriteableRegistry namedWriteableRegistry
5456
) {
5557
super(
5658
SuggestAnomalyDetectorParamAction.NAME,
@@ -64,7 +66,9 @@ public SuggestAnomalyDetectorParamTransportAction(
6466
AnalysisType.AD,
6567
searchFeatureDao,
6668
Name.getListStrs(Arrays.asList(ADSuggestName.values())),
67-
AnomalyDetector.class
69+
AnomalyDetector.class,
70+
namedWriteableRegistry
71+
6872
);
6973
}
7074

src/main/java/org/opensearch/ad/transport/ValidateAnomalyDetectorTransportAction.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.opensearch.common.inject.Inject;
2525
import org.opensearch.common.settings.Settings;
2626
import org.opensearch.commons.authuser.User;
27+
import org.opensearch.core.common.io.stream.NamedWriteableRegistry;
2728
import org.opensearch.core.xcontent.NamedXContentRegistry;
2829
import org.opensearch.rest.RestRequest;
2930
import org.opensearch.timeseries.feature.SearchFeatureDao;
@@ -50,7 +51,8 @@ public ValidateAnomalyDetectorTransportAction(
5051
ADIndexManagement anomalyDetectionIndices,
5152
ActionFilters actionFilters,
5253
TransportService transportService,
53-
SearchFeatureDao searchFeatureDao
54+
SearchFeatureDao searchFeatureDao,
55+
NamedWriteableRegistry namedWriteableRegistry
5456
) {
5557
super(
5658
ValidateAnomalyDetectorAction.NAME,
@@ -65,7 +67,8 @@ public ValidateAnomalyDetectorTransportAction(
6567
searchFeatureDao,
6668
AD_FILTER_BY_BACKEND_ROLES,
6769
ValidationAspect.DETECTOR,
68-
AnomalyDetector.class
70+
AnomalyDetector.class,
71+
namedWriteableRegistry
6972
);
7073
}
7174

src/main/java/org/opensearch/forecast/transport/SuggestForecasterParamTransportAction.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.opensearch.common.util.concurrent.ThreadContext;
2222
import org.opensearch.commons.authuser.User;
2323
import org.opensearch.core.action.ActionListener;
24+
import org.opensearch.core.common.io.stream.NamedWriteableRegistry;
2425
import org.opensearch.forecast.indices.ForecastIndexManagement;
2526
import org.opensearch.forecast.model.Forecaster;
2627
import org.opensearch.timeseries.AnalysisType;
@@ -50,7 +51,8 @@ public SuggestForecasterParamTransportAction(
5051
ForecastIndexManagement anomalyDetectionIndices,
5152
ActionFilters actionFilters,
5253
TransportService transportService,
53-
SearchFeatureDao searchFeatureDao
54+
SearchFeatureDao searchFeatureDao,
55+
NamedWriteableRegistry namedWriteableRegistry
5456
) {
5557
super(
5658
SuggestForecasterParamAction.NAME,
@@ -64,7 +66,8 @@ public SuggestForecasterParamTransportAction(
6466
AnalysisType.FORECAST,
6567
searchFeatureDao,
6668
Name.getListStrs(Arrays.asList(ForecastSuggestName.values())),
67-
Forecaster.class
69+
Forecaster.class,
70+
namedWriteableRegistry
6871
);
6972
}
7073

src/main/java/org/opensearch/forecast/transport/ValidateForecasterTransportAction.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.opensearch.common.inject.Inject;
1515
import org.opensearch.common.settings.Settings;
1616
import org.opensearch.commons.authuser.User;
17+
import org.opensearch.core.common.io.stream.NamedWriteableRegistry;
1718
import org.opensearch.core.xcontent.NamedXContentRegistry;
1819
import org.opensearch.forecast.indices.ForecastIndex;
1920
import org.opensearch.forecast.indices.ForecastIndexManagement;
@@ -45,7 +46,8 @@ public ValidateForecasterTransportAction(
4546
ForecastIndexManagement anomalyDetectionIndices,
4647
ActionFilters actionFilters,
4748
TransportService transportService,
48-
SearchFeatureDao searchFeatureDao
49+
SearchFeatureDao searchFeatureDao,
50+
NamedWriteableRegistry namedWriteableRegistry
4951
) {
5052
super(
5153
ValidateForecasterAction.NAME,
@@ -60,7 +62,8 @@ public ValidateForecasterTransportAction(
6062
searchFeatureDao,
6163
FORECAST_FILTER_BY_BACKEND_ROLES,
6264
ValidationAspect.FORECASTER,
63-
Forecaster.class
65+
Forecaster.class,
66+
namedWriteableRegistry
6467
);
6568
}
6669

src/main/java/org/opensearch/timeseries/transport/BaseSuggestConfigParamTransportAction.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.apache.commons.lang3.tuple.Pair;
2020
import org.apache.logging.log4j.LogManager;
2121
import org.apache.logging.log4j.Logger;
22+
import org.opensearch.action.ActionRequest;
2223
import org.opensearch.action.support.ActionFilters;
2324
import org.opensearch.action.support.HandledTransportAction;
2425
import org.opensearch.cluster.service.ClusterService;
@@ -28,6 +29,7 @@
2829
import org.opensearch.common.util.concurrent.ThreadContext;
2930
import org.opensearch.commons.authuser.User;
3031
import org.opensearch.core.action.ActionListener;
32+
import org.opensearch.core.common.io.stream.NamedWriteableRegistry;
3133
import org.opensearch.tasks.Task;
3234
import org.opensearch.timeseries.AnalysisType;
3335
import org.opensearch.timeseries.Name;
@@ -45,12 +47,13 @@
4547
import org.opensearch.transport.client.Client;
4648

4749
public abstract class BaseSuggestConfigParamTransportAction<ConfigType extends Config> extends
48-
HandledTransportAction<SuggestConfigParamRequest, SuggestConfigParamResponse> {
50+
HandledTransportAction<ActionRequest, SuggestConfigParamResponse> {
4951
public static final Logger logger = LogManager.getLogger(BaseSuggestConfigParamTransportAction.class);
5052

5153
protected final Client client;
5254
protected final SecurityClientUtil clientUtil;
5355
protected final SearchFeatureDao searchFeatureDao;
56+
protected final NamedWriteableRegistry namedWriteableRegistry;
5457
protected volatile Boolean filterByEnabled;
5558
protected Clock clock;
5659
protected AnalysisType context;
@@ -70,11 +73,13 @@ public BaseSuggestConfigParamTransportAction(
7073
AnalysisType context,
7174
SearchFeatureDao searchFeatureDao,
7275
Set<String> allSuggestParamStrs,
73-
Class<ConfigType> configTypeClass
76+
Class<ConfigType> configTypeClass,
77+
NamedWriteableRegistry namedWriteableRegistry
7478
) {
7579
super(actionName, transportService, actionFilters, SuggestConfigParamRequest::new);
7680
this.client = client;
7781
this.clientUtil = clientUtil;
82+
this.namedWriteableRegistry = namedWriteableRegistry;
7883
this.filterByEnabled = filterByBackendRoleSetting.get(settings);
7984
clusterService.getClusterSettings().addSettingsUpdateConsumer(filterByBackendRoleSetting, it -> filterByEnabled = it);
8085
this.clock = Clock.systemUTC();
@@ -86,7 +91,8 @@ public BaseSuggestConfigParamTransportAction(
8691
}
8792

8893
@Override
89-
protected void doExecute(Task task, SuggestConfigParamRequest request, ActionListener<SuggestConfigParamResponse> listener) {
94+
protected void doExecute(Task task, ActionRequest actionRequest, ActionListener<SuggestConfigParamResponse> listener) {
95+
SuggestConfigParamRequest request = SuggestConfigParamRequest.fromActionRequest(actionRequest, namedWriteableRegistry);
9096
User user = ParseUtils.getUserContext(client);
9197
try (ThreadContext.StoredContext context = client.threadPool().getThreadContext().stashContext()) {
9298
String resourceType = getResourceTypeFromClassName(configTypeClass.getSimpleName());

src/main/java/org/opensearch/timeseries/transport/BaseValidateConfigTransportAction.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import org.apache.logging.log4j.LogManager;
1616
import org.apache.logging.log4j.Logger;
17+
import org.opensearch.action.ActionRequest;
1718
import org.opensearch.action.search.SearchRequest;
1819
import org.opensearch.action.support.ActionFilters;
1920
import org.opensearch.action.support.HandledTransportAction;
@@ -23,6 +24,7 @@
2324
import org.opensearch.common.util.concurrent.ThreadContext;
2425
import org.opensearch.commons.authuser.User;
2526
import org.opensearch.core.action.ActionListener;
27+
import org.opensearch.core.common.io.stream.NamedWriteableRegistry;
2628
import org.opensearch.core.xcontent.NamedXContentRegistry;
2729
import org.opensearch.index.IndexNotFoundException;
2830
import org.opensearch.index.query.QueryBuilders;
@@ -47,7 +49,7 @@
4749
import org.opensearch.transport.client.Client;
4850

4951
public abstract class BaseValidateConfigTransportAction<IndexType extends Enum<IndexType> & TimeSeriesIndex, IndexManagementType extends IndexManagement<IndexType>, ConfigType extends Config>
50-
extends HandledTransportAction<ValidateConfigRequest, ValidateConfigResponse> {
52+
extends HandledTransportAction<ActionRequest, ValidateConfigResponse> {
5153
public static final Logger logger = LogManager.getLogger(BaseValidateConfigTransportAction.class);
5254

5355
protected final Client client;
@@ -56,6 +58,7 @@ public abstract class BaseValidateConfigTransportAction<IndexType extends Enum<I
5658
protected final NamedXContentRegistry xContentRegistry;
5759
protected final IndexManagementType indexManagement;
5860
protected final SearchFeatureDao searchFeatureDao;
61+
protected final NamedWriteableRegistry namedWriteableRegistry;
5962
protected volatile Boolean filterByEnabled;
6063
protected Clock clock;
6164
protected Settings settings;
@@ -75,14 +78,16 @@ public BaseValidateConfigTransportAction(
7578
SearchFeatureDao searchFeatureDao,
7679
Setting<Boolean> filterByBackendRoleSetting,
7780
ValidationAspect validationAspect,
78-
Class<ConfigType> configTypeClass
81+
Class<ConfigType> configTypeClass,
82+
NamedWriteableRegistry namedWriteableRegistry
7983
) {
8084
super(actionName, transportService, actionFilters, ValidateConfigRequest::new);
8185
this.client = client;
8286
this.clientUtil = clientUtil;
8387
this.clusterService = clusterService;
8488
this.xContentRegistry = xContentRegistry;
8589
this.indexManagement = indexManagement;
90+
this.namedWriteableRegistry = namedWriteableRegistry;
8691
this.filterByEnabled = filterByBackendRoleSetting.get(settings);
8792
clusterService.getClusterSettings().addSettingsUpdateConsumer(filterByBackendRoleSetting, it -> filterByEnabled = it);
8893
this.searchFeatureDao = searchFeatureDao;
@@ -93,7 +98,8 @@ public BaseValidateConfigTransportAction(
9398
}
9499

95100
@Override
96-
protected void doExecute(Task task, ValidateConfigRequest request, ActionListener<ValidateConfigResponse> listener) {
101+
protected void doExecute(Task task, ActionRequest actionRequest, ActionListener<ValidateConfigResponse> listener) {
102+
ValidateConfigRequest request = ValidateConfigRequest.fromActionRequest(actionRequest, namedWriteableRegistry);
97103
User user = ParseUtils.getUserContext(client);
98104
try (ThreadContext.StoredContext context = client.threadPool().getThreadContext().stashContext()) {
99105
String resourceType = getResourceTypeFromClassName(configTypeClass.getSimpleName());

0 commit comments

Comments
 (0)