66package org .opensearch .dataprepper .plugins .processor .mutateevent ;
77
88import com .fasterxml .jackson .annotation .JsonClassDescription ;
9+ import com .fasterxml .jackson .annotation .JsonIgnore ;
910import com .fasterxml .jackson .annotation .JsonProperty ;
1011import com .fasterxml .jackson .annotation .JsonPropertyDescription ;
1112import com .fasterxml .jackson .annotation .JsonPropertyOrder ;
1213import jakarta .validation .Valid ;
13- import jakarta .validation .constraints .AssertFalse ;
1414import jakarta .validation .constraints .AssertTrue ;
1515import jakarta .validation .constraints .NotEmpty ;
1616import jakarta .validation .constraints .NotNull ;
2323import org .opensearch .dataprepper .model .event .EventKeyConfiguration ;
2424import org .opensearch .dataprepper .model .event .EventKeyFactory ;
2525
26+ import java .util .Collections ;
2627import java .util .List ;
28+ import java .util .Set ;
29+ import java .util .regex .Pattern ;
30+ import java .util .regex .PatternSyntaxException ;
31+ import java .util .stream .Collectors ;
2732
2833@ ConditionalRequired (value = {
2934 @ IfThenElse (
30- ifFulfilled = {@ SchemaProperty (field = "entries" , value = "null" )},
35+ ifFulfilled = {@ SchemaProperty (field = "entries" , value = "null" ), @ SchemaProperty ( field = "with_keys_regex" , value = "null" ) },
3136 thenExpect = {@ SchemaProperty (field = "with_keys" )}
3237 ),
3338 @ IfThenElse (
34- ifFulfilled = {@ SchemaProperty (field = "with_keys" , value = "null" )},
39+ ifFulfilled = {@ SchemaProperty (field = "entries" , value = "null" ), @ SchemaProperty (field = "with_keys" , value = "null" )},
40+ thenExpect = {@ SchemaProperty (field = "with_keys_regex" )}
41+ ),
42+ @ IfThenElse (
43+ ifFulfilled = {@ SchemaProperty (field = "with_keys" , value = "null" ), @ SchemaProperty (field = "with_keys_regex" , value = "null" )},
3544 thenExpect = {@ SchemaProperty (field = "entries" )}
3645 )
3746})
3847@ JsonPropertyOrder
3948@ JsonClassDescription ("The <code>delete_entries</code> processor deletes fields from events. " +
40- "You can define the keys you want to delete in the <code>with_keys</code> configuration. " +
41- "Those keys and their values are deleted from events." )
49+ "You can specify the keys of the fields you want to delete using the <code>with_keys</code> " +
50+ "or <code>with_keys_regex</code> configuration options. You can only use one per entry. " +
51+ "Those keys and their values are deleted from the events." )
4252public class DeleteEntryProcessorConfig {
4353
4454 @ JsonPropertyOrder
4555 public static class Entry {
46- @ NotEmpty
47- @ NotNull
4856 @ JsonProperty ("with_keys" )
4957 @ EventKeyConfiguration (EventKeyFactory .EventAction .DELETE )
5058 @ JsonPropertyDescription ("A list of keys to be deleted." )
5159 private List <@ NotNull @ NotEmpty EventKey > withKeys ;
5260
61+ @ JsonProperty ("with_keys_regex" )
62+ @ JsonPropertyDescription ("A list of regex patterns to match keys to be deleted." )
63+ private List <String > withKeysRegex ;
64+
65+ @ JsonProperty ("exclude_from_delete" )
66+ @ JsonPropertyDescription ("A list of keys to exclude from deletion when using with_keys_regex." )
67+ private Set <EventKey > excludeFromDelete ;
68+
5369 @ JsonProperty ("delete_when" )
5470 @ JsonPropertyDescription ("Specifies under what condition the deletion should be performed. " +
5571 "By default, keys are always deleted. Example: <code>/mykey == \" ---\" </code>" )
@@ -67,8 +83,49 @@ public static class Entry {
6783 @ JsonProperty ("iterate_on" )
6884 private String iterateOn ;
6985
86+ @ AssertTrue (message = "exclude_from_delete only applies when with_keys_regex is configured." )
87+ boolean isExcludeFromDeleteValid () {
88+ return excludeFromDelete != null && !excludeFromDelete .isEmpty () && withKeysRegex != null && !withKeysRegex .isEmpty ();
89+ }
90+
91+ @ JsonIgnore
92+ private List <Pattern > withKeysRegexPatterns ;
93+
94+ private void setWithKeysRegexPatterns () {
95+ withKeysRegexPatterns = getWithKeysRegex ().stream ()
96+ .map (Pattern ::compile )
97+ .collect (Collectors .toList ());
98+ }
99+
100+ @ AssertTrue (message = "Invalid regex pattern found in with_keys_regex." )
101+ public boolean isValidWithKeysRegexPattern () {
102+ if (withKeysRegex != null && !withKeysRegex .isEmpty ()) {
103+ try {
104+ setWithKeysRegexPatterns ();
105+ } catch (PatternSyntaxException e ) {
106+ return false ;
107+ }
108+ }
109+ return true ;
110+ }
111+
70112 public List <EventKey > getWithKeys () {
71- return withKeys ;
113+ return withKeys != null ? withKeys : Collections .emptyList ();
114+ }
115+
116+ public List <String > getWithKeysRegex () {
117+ return withKeysRegex != null ? withKeysRegex : Collections .emptyList ();
118+ }
119+
120+ public List <Pattern > getWithKeysRegexPattern () {
121+ if (withKeysRegexPatterns == null && withKeysRegex != null && !withKeysRegex .isEmpty ()) {
122+ setWithKeysRegexPatterns ();
123+ }
124+ return withKeysRegexPatterns != null ? withKeysRegexPatterns : Collections .emptyList ();
125+ }
126+
127+ public Set <EventKey > getExcludeFromDelete () {
128+ return excludeFromDelete != null ? excludeFromDelete : Collections .emptySet ();
72129 }
73130
74131 public String getDeleteWhen () {
@@ -82,17 +139,20 @@ public String getDeleteFromElementWhen() {
82139 }
83140
84141 public Entry (final List <EventKey > withKeys ,
142+ final List <String > withKeysRegex ,
143+ final Set <EventKey > excludeFromDelete ,
85144 final String deleteWhen ,
86145 final String iterateOn ,
87146 final String deleteFromElementWhen ) {
88147 this .withKeys = withKeys ;
148+ this .withKeysRegex = withKeysRegex ;
149+ this .excludeFromDelete = excludeFromDelete ;
89150 this .deleteWhen = deleteWhen ;
90151 this .deleteFromElementWhen = deleteFromElementWhen ;
91152 this .iterateOn = iterateOn ;
92153 }
93154
94155 public Entry () {
95-
96156 }
97157 }
98158
@@ -101,6 +161,14 @@ public Entry() {
101161 @ JsonPropertyDescription ("A list of keys to be deleted. May not be used with entries." )
102162 private List <@ NotNull @ NotEmpty EventKey > withKeys ;
103163
164+ @ JsonProperty ("with_keys_regex" )
165+ @ JsonPropertyDescription ("A list of regex patterns that match keys to be deleted from an event. May not be used with entries." )
166+ private List <String > withKeysRegex ;
167+
168+ @ JsonProperty ("exclude_from_delete" )
169+ @ JsonPropertyDescription ("A list of keys to exclude from deletion when using with_keys_regex." )
170+ private Set <EventKey > excludeFromDelete ;
171+
104172 @ JsonProperty ("delete_when" )
105173 @ JsonPropertyDescription ("Specifies under what condition the deletion should be performed." )
106174 private String deleteWhen ;
@@ -110,15 +178,46 @@ public Entry() {
110178 @ JsonPropertyDescription ("A list of entries to delete from the event." )
111179 private List <Entry > entries ;
112180
113- @ AssertTrue (message = "Either 'entries' or 'with_keys' must be specified, but neither was found " )
181+ @ AssertTrue (message = "One of the following must be provided: 'entries', 'with_keys', or 'with_keys_regex'. None of these are configured. " )
114182 boolean isConfigurationPresent () {
115- return entries != null || withKeys != null ;
183+ return entries != null || withKeys != null || withKeysRegex != null ;
184+ }
185+
186+ @ AssertTrue (message = "You can only use one of the following at a time: 'entries', 'with_keys', or 'with_keys_regex'" )
187+ boolean hasOnlyOneConfiguration () {
188+ int count = 0 ;
189+ if (entries != null ) count ++;
190+ if (withKeys != null ) count ++;
191+ if (withKeysRegex != null ) count ++;
192+ return count == 1 ;
193+ }
194+
195+ @ AssertTrue (message = "exclude_from_delete only applies when with_keys_regex is configured." )
196+ boolean isExcludeFromDeleteValid () {
197+ return excludeFromDelete != null && !excludeFromDelete .isEmpty () && withKeysRegex != null && !withKeysRegex .isEmpty ();
116198 }
117199
118- @ AssertFalse (message = "Either use 'entries' OR 'with_keys' with 'delete_when' configuration, but not both" )
119- boolean hasBothConfigurations () {
120- return entries != null && withKeys != null ;
200+ @ JsonIgnore
201+ private List <Pattern > withKeysRegexPatterns ;
202+
203+ private void setWithKeysRegexPatterns () {
204+ withKeysRegexPatterns = getWithKeysRegex ().stream ()
205+ .map (Pattern ::compile )
206+ .collect (Collectors .toList ());
207+ }
208+
209+ @ AssertTrue (message = "Invalid regex pattern in 'with_keys_regex'" )
210+ boolean isValidWithKeysRegexPattern () {
211+ if (withKeysRegex != null && !withKeysRegex .isEmpty ()) {
212+ try {
213+ setWithKeysRegexPatterns ();
214+ } catch (PatternSyntaxException e ) {
215+ return false ;
216+ }
217+ }
218+ return true ;
121219 }
220+
122221 @ JsonPropertyDescription (
123222 "Specifies the key of the list of object to iterate over and delete the keys specified in with_keys." )
124223 @ JsonProperty ("iterate_on" )
@@ -129,7 +228,22 @@ boolean hasBothConfigurations() {
129228 private String deleteFromElementWhen ;
130229
131230 public List <EventKey > getWithKeys () {
132- return withKeys ;
231+ return withKeys != null ? withKeys : Collections .emptyList ();
232+ }
233+
234+ public List <String > getWithKeysRegex () {
235+ return withKeysRegex != null ? withKeysRegex : Collections .emptyList ();
236+ }
237+
238+ public List <Pattern > getWithKeysRegexPattern () {
239+ if (withKeysRegexPatterns == null && withKeysRegex != null && !withKeysRegex .isEmpty ()) {
240+ setWithKeysRegexPatterns ();
241+ }
242+ return withKeysRegexPatterns != null ? withKeysRegexPatterns : Collections .emptyList ();
243+ }
244+
245+ public Set <EventKey > getExcludeFromDelete () {
246+ return excludeFromDelete != null ? excludeFromDelete : Collections .emptySet ();
133247 }
134248
135249 public String getDeleteWhen () {
0 commit comments