Skip to content

Commit 14be575

Browse files
ruai0511Lingxi Chen
authored andcommitted
[rule based autotagging] Add Update Rule API Logic (opensearch-project#17797)
--------- Signed-off-by: Lingxi Chen <[email protected]> Signed-off-by: Kaushal Kumar <[email protected]> Co-authored-by: Lingxi Chen <[email protected]>
1 parent 9b01cd2 commit 14be575

File tree

54 files changed

+1172
-317
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1172
-317
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1313
- Implement parallel shard refresh behind cluster settings ([#17782](https://github.com/opensearch-project/OpenSearch/pull/17782))
1414
- Bump OpenSearch Core main branch to 3.0.0 ([#18039](https://github.com/opensearch-project/OpenSearch/pull/18039))
1515
- [Rule based Auto-tagging] Add wlm `ActionFilter` ([#17791](https://github.com/opensearch-project/OpenSearch/pull/17791))
16+
- [Rule based auto-tagging] Add update rule API ([#17797](https://github.com/opensearch-project/OpenSearch/pull/17797))
1617
- Update API of Message in index to add the timestamp for lag calculation in ingestion polling ([#17977](https://github.com/opensearch-project/OpenSearch/pull/17977/))
1718
- Add Warm Disk Threshold Allocation Decider for Warm shards ([#18082](https://github.com/opensearch-project/OpenSearch/pull/18082))
1819
- Add composite directory factory ([#17988](https://github.com/opensearch-project/OpenSearch/pull/17988))

modules/autotagging-commons/common/src/main/java/org/opensearch/rule/RulePersistenceService.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010

1111
import org.opensearch.action.support.clustermanager.AcknowledgedResponse;
1212
import org.opensearch.core.action.ActionListener;
13+
import org.opensearch.rule.action.CreateRuleRequest;
14+
import org.opensearch.rule.action.CreateRuleResponse;
15+
import org.opensearch.rule.action.DeleteRuleRequest;
16+
import org.opensearch.rule.action.GetRuleRequest;
17+
import org.opensearch.rule.action.GetRuleResponse;
18+
import org.opensearch.rule.action.UpdateRuleRequest;
19+
import org.opensearch.rule.action.UpdateRuleResponse;
1320

1421
/**
1522
* Interface for a service that handles rule persistence CRUD operations.
@@ -37,4 +44,11 @@ public interface RulePersistenceService {
3744
* @param listener The listener that will handle the response or failure.
3845
*/
3946
void deleteRule(DeleteRuleRequest request, ActionListener<AcknowledgedResponse> listener);
47+
48+
/**
49+
* Update rule based on the provided request.
50+
* @param request The request containing the details for updating the rule.
51+
* @param listener The listener that will handle the response or failure.
52+
*/
53+
void updateRule(UpdateRuleRequest request, ActionListener<UpdateRuleResponse> listener);
4054
}

modules/autotagging-commons/common/src/main/java/org/opensearch/rule/RuleQueryMapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package org.opensearch.rule;
1010

1111
import org.opensearch.common.annotation.ExperimentalApi;
12+
import org.opensearch.rule.action.GetRuleRequest;
1213

1314
/**
1415
* This interface is responsible for creating query objects which storage layer can use

modules/autotagging-commons/common/src/main/java/org/opensearch/rule/RuleRoutingService.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
package org.opensearch.rule;
1010

1111
import org.opensearch.core.action.ActionListener;
12+
import org.opensearch.rule.action.CreateRuleRequest;
13+
import org.opensearch.rule.action.CreateRuleResponse;
14+
import org.opensearch.rule.action.UpdateRuleRequest;
15+
import org.opensearch.rule.action.UpdateRuleResponse;
1216

1317
/**
1418
* Interface that handles rule routing logic
@@ -22,4 +26,11 @@ public interface RuleRoutingService {
2226
* @param listener listener to handle the final response
2327
*/
2428
void handleCreateRuleRequest(CreateRuleRequest request, ActionListener<CreateRuleResponse> listener);
29+
30+
/**
31+
* Handles a update rule request by routing it to the appropriate node.
32+
* @param request the update rule request
33+
* @param listener listener to handle the final response
34+
*/
35+
void handleUpdateRuleRequest(UpdateRuleRequest request, ActionListener<UpdateRuleResponse> listener);
2536
}

modules/autotagging-commons/common/src/main/java/org/opensearch/rule/RuleUtils.java

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,19 @@
99
package org.opensearch.rule;
1010

1111
import org.opensearch.common.annotation.ExperimentalApi;
12+
import org.opensearch.rule.action.UpdateRuleRequest;
1213
import org.opensearch.rule.autotagging.Attribute;
14+
import org.opensearch.rule.autotagging.FeatureType;
1315
import org.opensearch.rule.autotagging.Rule;
1416

17+
import java.nio.charset.StandardCharsets;
18+
import java.time.Instant;
1519
import java.util.Collections;
20+
import java.util.List;
1621
import java.util.Map;
1722
import java.util.Optional;
1823
import java.util.Set;
24+
import java.util.UUID;
1925

2026
/**
2127
* Utility class for operations related to {@link Rule} objects.
@@ -29,6 +35,24 @@ public class RuleUtils {
2935
*/
3036
public RuleUtils() {}
3137

38+
/**
39+
* Computes a UUID-based hash string for a rule based on its key attributes.
40+
* @param description the rule's description
41+
* @param featureType the rule's feature type
42+
* @param attributeMap the rule's attribute map (will use its toString representation)
43+
* @param featureValue the rule's feature value
44+
*/
45+
public static String computeRuleHash(
46+
String description,
47+
FeatureType featureType,
48+
Map<Attribute, Set<String>> attributeMap,
49+
String featureValue
50+
) {
51+
String combined = description + "|" + featureType.getName() + "|" + attributeMap.toString() + "|" + featureValue;
52+
UUID uuid = UUID.nameUUIDFromBytes(combined.getBytes(StandardCharsets.UTF_8));
53+
return uuid.toString();
54+
}
55+
3256
/**
3357
* Checks if a duplicate rule exists and returns its id.
3458
* Two rules are considered to be duplicate when meeting all the criteria below
@@ -38,12 +62,11 @@ public RuleUtils() {}
3862
* between the current rule and the one being checked.
3963
*
4064
* @param rule The rule to be validated against ruleMap.
41-
* @param ruleMap This map contains existing rules to be checked
65+
* @param ruleList This list contains existing rules to be checked
4266
*/
43-
public static Optional<String> getDuplicateRuleId(Rule rule, Map<String, Rule> ruleMap) {
67+
public static Optional<String> getDuplicateRuleId(Rule rule, List<Rule> ruleList) {
4468
Map<Attribute, Set<String>> targetAttributeMap = rule.getAttributeMap();
45-
for (Map.Entry<String, Rule> entry : ruleMap.entrySet()) {
46-
Rule currRule = entry.getValue();
69+
for (Rule currRule : ruleList) {
4770
Map<Attribute, Set<String>> existingAttributeMap = currRule.getAttributeMap();
4871

4972
if (rule.getFeatureType() != currRule.getFeatureType() || targetAttributeMap.size() != existingAttributeMap.size()) {
@@ -59,9 +82,30 @@ public static Optional<String> getDuplicateRuleId(Rule rule, Map<String, Rule> r
5982
}
6083
}
6184
if (allAttributesIntersect) {
62-
return Optional.of(entry.getKey());
85+
return Optional.of(currRule.getId());
6386
}
6487
}
6588
return Optional.empty();
6689
}
90+
91+
/**
92+
* Creates an updated {@link Rule} object by applying non-null fields from the given {@link UpdateRuleRequest}
93+
* to the original rule. Fields not provided in the request will retain their values from the original rule.
94+
* @param originalRule the original rule to update
95+
* @param request the request containing the new values for the rule
96+
* @param featureType the feature type to assign to the updated rule
97+
*/
98+
public static Rule composeUpdatedRule(Rule originalRule, UpdateRuleRequest request, FeatureType featureType) {
99+
String requestDescription = request.getDescription();
100+
Map<Attribute, Set<String>> requestMap = request.getAttributeMap();
101+
String requestLabel = request.getFeatureValue();
102+
return new Rule(
103+
originalRule.getId(),
104+
requestDescription == null ? originalRule.getDescription() : requestDescription,
105+
requestMap == null || requestMap.isEmpty() ? originalRule.getAttributeMap() : requestMap,
106+
featureType,
107+
requestLabel == null ? originalRule.getFeatureValue() : requestLabel,
108+
Instant.now().toString()
109+
);
110+
}
67111
}

modules/autotagging-commons/common/src/main/java/org/opensearch/rule/CreateRuleRequest.java renamed to modules/autotagging-commons/common/src/main/java/org/opensearch/rule/action/CreateRuleRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* compatible open source license.
77
*/
88

9-
package org.opensearch.rule;
9+
package org.opensearch.rule.action;
1010

1111
import org.opensearch.action.ActionRequest;
1212
import org.opensearch.action.ActionRequestValidationException;

modules/autotagging-commons/common/src/main/java/org/opensearch/rule/CreateRuleResponse.java renamed to modules/autotagging-commons/common/src/main/java/org/opensearch/rule/action/CreateRuleResponse.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* compatible open source license.
77
*/
88

9-
package org.opensearch.rule;
9+
package org.opensearch.rule.action;
1010

1111
import org.opensearch.core.action.ActionResponse;
1212
import org.opensearch.core.common.io.stream.StreamInput;
@@ -17,15 +17,12 @@
1717
import org.opensearch.rule.autotagging.Rule;
1818

1919
import java.io.IOException;
20-
import java.util.Map;
21-
22-
import static org.opensearch.rule.autotagging.Rule._ID_STRING;
2320

2421
/**
2522
* Response for the create API for Rule
2623
* Example response:
2724
* {
28-
* "_id":"wi6VApYBoX5wstmtU_8l",
25+
* "id":"wi6VApYBoX5wstmtU_8l",
2926
* "description":"description1",
3027
* "index_pattern":["log*", "uvent*"],
3128
* "workload_group":"poOiU851RwyLYvV5lbvv5w",
@@ -34,16 +31,13 @@
3431
* @opensearch.experimental
3532
*/
3633
public class CreateRuleResponse extends ActionResponse implements ToXContent, ToXContentObject {
37-
private final String _id;
3834
private final Rule rule;
3935

4036
/**
4137
* contructor for CreateRuleResponse
42-
* @param id - the id for the rule created
4338
* @param rule - the rule created
4439
*/
45-
public CreateRuleResponse(String id, final Rule rule) {
46-
this._id = id;
40+
public CreateRuleResponse(final Rule rule) {
4741
this.rule = rule;
4842
}
4943

@@ -52,19 +46,17 @@ public CreateRuleResponse(String id, final Rule rule) {
5246
* @param in - The {@link StreamInput} instance to read from.
5347
*/
5448
public CreateRuleResponse(StreamInput in) throws IOException {
55-
_id = in.readString();
5649
rule = new Rule(in);
5750
}
5851

5952
@Override
6053
public void writeTo(StreamOutput out) throws IOException {
61-
out.writeString(_id);
6254
rule.writeTo(out);
6355
}
6456

6557
@Override
6658
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
67-
return rule.toXContent(builder, new MapParams(Map.of(_ID_STRING, _id)));
59+
return rule.toXContent(builder, params);
6860
}
6961

7062
/**

modules/autotagging-commons/common/src/main/java/org/opensearch/rule/DeleteRuleRequest.java renamed to modules/autotagging-commons/common/src/main/java/org/opensearch/rule/action/DeleteRuleRequest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* compatible open source license.
77
*/
88

9-
package org.opensearch.rule;
9+
package org.opensearch.rule.action;
1010

1111
import org.opensearch.action.ActionRequest;
1212
import org.opensearch.action.ActionRequestValidationException;
@@ -80,7 +80,7 @@ public String getRuleId() {
8080
*
8181
* @return The feature type.
8282
*/
83-
public FeatureType getFeatureType() {
83+
FeatureType getFeatureType() {
8484
return featureType;
8585
}
8686
}

modules/autotagging-commons/common/src/main/java/org/opensearch/rule/GetRuleRequest.java renamed to modules/autotagging-commons/common/src/main/java/org/opensearch/rule/action/GetRuleRequest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* compatible open source license.
77
*/
88

9-
package org.opensearch.rule;
9+
package org.opensearch.rule.action;
1010

1111
import org.opensearch.action.ActionRequest;
1212
import org.opensearch.action.ActionRequestValidationException;
@@ -67,7 +67,7 @@ public GetRuleRequest(StreamInput in) throws IOException {
6767
@Override
6868
public ActionRequestValidationException validate() {
6969
if (RuleValidator.isEmpty(id)) {
70-
throw new IllegalArgumentException(Rule._ID_STRING + " cannot be empty.");
70+
throw new IllegalArgumentException(Rule.ID_STRING + " cannot be empty.");
7171
}
7272
if (RuleValidator.isEmpty(searchAfter)) {
7373
throw new IllegalArgumentException("search_after cannot be empty.");

modules/autotagging-commons/common/src/main/java/org/opensearch/rule/GetRuleResponse.java renamed to modules/autotagging-commons/common/src/main/java/org/opensearch/rule/action/GetRuleResponse.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* compatible open source license.
77
*/
88

9-
package org.opensearch.rule;
9+
package org.opensearch.rule.action;
1010

1111
import org.opensearch.common.annotation.ExperimentalApi;
1212
import org.opensearch.core.action.ActionResponse;
@@ -18,17 +18,15 @@
1818
import org.opensearch.rule.autotagging.Rule;
1919

2020
import java.io.IOException;
21-
import java.util.Map;
22-
23-
import static org.opensearch.rule.autotagging.Rule._ID_STRING;
21+
import java.util.List;
2422

2523
/**
2624
* Response for the get API for Rule.
2725
* Example response:
2826
* {
2927
* "rules": [
3028
* {
31-
* "_id": "z1MJApUB0zgMcDmz-UQq",
29+
* "id": "z1MJApUB0zgMcDmz-UQq",
3230
* "description": "Rule for tagging workload_group_id to index123"
3331
* "index_pattern": ["index123"],
3432
* "workload_group": "workload_group_id",
@@ -42,15 +40,15 @@
4240
*/
4341
@ExperimentalApi
4442
public class GetRuleResponse extends ActionResponse implements ToXContent, ToXContentObject {
45-
private final Map<String, Rule> rules;
43+
private final List<Rule> rules;
4644
private final String searchAfter;
4745

4846
/**
4947
* Constructor for GetRuleResponse
5048
* @param rules - Rules get from the request
5149
* @param searchAfter - The sort value used for pagination.
5250
*/
53-
public GetRuleResponse(final Map<String, Rule> rules, String searchAfter) {
51+
public GetRuleResponse(final List<Rule> rules, String searchAfter) {
5452
this.rules = rules;
5553
this.searchAfter = searchAfter;
5654
}
@@ -60,21 +58,21 @@ public GetRuleResponse(final Map<String, Rule> rules, String searchAfter) {
6058
* @param in - The {@link StreamInput} instance to read from.
6159
*/
6260
public GetRuleResponse(StreamInput in) throws IOException {
63-
this(in.readMap(StreamInput::readString, Rule::new), in.readOptionalString());
61+
this(in.readList(Rule::new), in.readOptionalString());
6462
}
6563

6664
@Override
6765
public void writeTo(StreamOutput out) throws IOException {
68-
out.writeMap(rules, StreamOutput::writeString, (outStream, rule) -> rule.writeTo(outStream));
66+
out.writeList(rules);
6967
out.writeOptionalString(searchAfter);
7068
}
7169

7270
@Override
7371
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
7472
builder.startObject();
7573
builder.startArray("rules");
76-
for (Map.Entry<String, Rule> entry : rules.entrySet()) {
77-
entry.getValue().toXContent(builder, new MapParams(Map.of(_ID_STRING, entry.getKey())));
74+
for (Rule rule : rules) {
75+
rule.toXContent(builder, params);
7876
}
7977
builder.endArray();
8078
if (searchAfter != null && !searchAfter.isEmpty()) {
@@ -87,7 +85,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
8785
/**
8886
* rules getter
8987
*/
90-
public Map<String, Rule> getRules() {
88+
public List<Rule> getRules() {
9189
return rules;
9290
}
9391
}

0 commit comments

Comments
 (0)