diff --git a/changelog/unreleased/issue-26009.toml b/changelog/unreleased/issue-26009.toml new file mode 100644 index 000000000000..71411c891a65 --- /dev/null +++ b/changelog/unreleased/issue-26009.toml @@ -0,0 +1,5 @@ +type = "fixed" +message = "Fix extractors being deleted when an input is started, stopped, or updated." + +issues = ["26009"] +pulls = ["26198"] diff --git a/graylog2-server/src/main/java/org/graylog2/inputs/InputImpl.java b/graylog2-server/src/main/java/org/graylog2/inputs/InputImpl.java index b832da15275b..de4be9ff5db8 100644 --- a/graylog2-server/src/main/java/org/graylog2/inputs/InputImpl.java +++ b/graylog2-server/src/main/java/org/graylog2/inputs/InputImpl.java @@ -120,6 +120,15 @@ public Map getStaticFields() { return result; } + /** + * The embedded extractor documents. They are modified through targeted update operations (see + * {@code InputServiceImpl#addExtractor} etc.) and only modeled here so that they survive full document + * replacements when saving an input. + */ + @Nullable + @JsonProperty(EMBEDDED_EXTRACTORS) + public abstract List> getEmbeddedExtractors(); + @NotNull @JsonProperty(FIELD_TYPE) public abstract String getType(); @@ -179,6 +188,9 @@ public static Builder create() { @JsonProperty(EMBEDDED_STATIC_FIELDS) public abstract Builder setEmbeddedStaticFields(List> staticFields); + @JsonProperty(EMBEDDED_EXTRACTORS) + public abstract Builder setEmbeddedExtractors(List> extractors); + @JsonProperty(FIELD_TYPE) public abstract Builder setType(String type); @@ -226,6 +238,11 @@ public Map getFields() { doc.put(EMBEDDED_STATIC_FIELDS, getEmbeddedStaticFields()); } + final List> extractors = getEmbeddedExtractors(); + if (extractors != null && !extractors.isEmpty()) { + doc.put(EMBEDDED_EXTRACTORS, extractors); + } + if (getContentPack() != null) { doc.put(FIELD_CONTENT_PACK, getContentPack()); } diff --git a/graylog2-server/src/main/java/org/graylog2/inputs/InputServiceImpl.java b/graylog2-server/src/main/java/org/graylog2/inputs/InputServiceImpl.java index 63e7b9a868fa..a2d6c643e49d 100644 --- a/graylog2-server/src/main/java/org/graylog2/inputs/InputServiceImpl.java +++ b/graylog2-server/src/main/java/org/graylog2/inputs/InputServiceImpl.java @@ -296,6 +296,11 @@ private InputImpl.Builder buildFromMap(Map fields) { builder.setEmbeddedStaticFields(staticFields); } + final List> extractors = (List>) fields.get(InputImpl.EMBEDDED_EXTRACTORS); + if (extractors != null && !extractors.isEmpty()) { + builder.setEmbeddedExtractors(extractors); + } + if (!isGlobal) { builder.setNodeId((String) fields.get(MessageInput.FIELD_NODE_ID)); } @@ -749,8 +754,12 @@ private InputImpl withEncryptedFields(InputImpl input) { @Override public void persistDesiredState(Input input, IOState.Type desiredState) throws ValidationException { - final Input updatedInput = input.withDesiredState(desiredState); - saveWithoutEvents(updatedInput); + // Use a targeted update instead of saving the whole input to avoid overwriting concurrent changes + // to other parts of the input document. + collection.updateOne( + MongoUtils.idEq(input.getId()), + Updates.set(InputImpl.FIELD_DESIRED_STATE, desiredState.name()) + ); } @Override diff --git a/graylog2-server/src/test/java/org/graylog2/inputs/InputServiceImplTest.java b/graylog2-server/src/test/java/org/graylog2/inputs/InputServiceImplTest.java index 3aad16cc37e8..11ab7abd15d7 100644 --- a/graylog2-server/src/test/java/org/graylog2/inputs/InputServiceImplTest.java +++ b/graylog2-server/src/test/java/org/graylog2/inputs/InputServiceImplTest.java @@ -448,6 +448,7 @@ public void persistedDocumentContainsOnlyExpectedFields(MongoCollections mongoCo .setEmbeddedStaticFields(List.of( Map.of(InputImpl.FIELD_STATIC_FIELD_KEY, "static_key", InputImpl.FIELD_STATIC_FIELD_VALUE, "static_value"))) + .setEmbeddedExtractors(List.of(createCopyInputExtractor().getPersistedFields())) .build(); final String id = inputService.save(input); @@ -466,6 +467,7 @@ public void persistedDocumentContainsOnlyExpectedFields(MongoCollections mongoCo InputImpl.FIELD_GLOBAL, InputImpl.FIELD_CONFIGURATION, InputImpl.EMBEDDED_STATIC_FIELDS, + InputImpl.EMBEDDED_EXTRACTORS, InputImpl.FIELD_DESIRED_STATE, InputImpl.FIELD_CONTENT_PACK, InputImpl.FIELD_NODE_ID