/** * Reads Json data for the specified config type and config name (if applicable) from zookeeper, * applies the patch from patchData, and writes it back to Zookeeper in a pretty print format. * Patching JSON flattens existing formatting, so this will keep configs readable. The * curatorclient should be started already. * * @param configurationType GLOBAL, PARSER, etc. * @param configName e.g. bro, yaf, snort * @param patchData a JSON patch in the format specified by RFC 6902 * @param client access to zookeeeper */ public static void applyConfigPatchToZookeeper( ConfigurationType configurationType, Optional<String> configName, byte[] patchData, CuratorFramework client) throws Exception { byte[] configData = readConfigBytesFromZookeeper(configurationType, configName, client); byte[] prettyPatchedConfig = JSONUtils.INSTANCE.applyPatch(patchData, configData); // ensure the patch produces a valid result; otherwise exception thrown during deserialization String prettyPatchedConfigStr = new String(prettyPatchedConfig); configurationType.deserialize(prettyPatchedConfigStr); writeConfigToZookeeper(configurationType, configName, prettyPatchedConfig, client); }
default Document getPatchedDocument(RetrieveLatestDao retrieveLatestDao, PatchRequest request, Optional<Long> optionalTimestamp ) throws OriginalNotFoundException, IOException { String guid = request.getGuid(); String sensorType = request.getSensorType(); String documentID = null; Long timestamp = optionalTimestamp.orElse(System.currentTimeMillis()); Map<String, Object> originalSource = request.getSource(); if (originalSource == null) { // no document source provided, lookup the latest Document toPatch = retrieveLatestDao.getLatest(guid, sensorType); if(toPatch != null && toPatch.getDocument() != null) { originalSource = toPatch.getDocument(); documentID = toPatch.getDocumentID().orElse(null); } else { String error = format("Document does not exist, but is required; guid=%s, sensorType=%s", guid, sensorType); throw new OriginalNotFoundException(error); } } Map<String, Object> patchedSource = JSONUtils.INSTANCE.applyPatch(request.getPatch(), originalSource); return new Document(patchedSource, guid, sensorType, timestamp, documentID); } }
@Test public void applyPatch_modifies_complex_source_json_doc() throws IOException { String actual = new String(JSONUtils.INSTANCE.applyPatch(patchComplexJson, complexJson)); assertThat(JSONUtils.INSTANCE.load(actual, JSONUtils.MAP_SUPPLIER), equalTo(JSONUtils.INSTANCE.load(expectedComplexJson, JSONUtils.MAP_SUPPLIER))); }
@Test public void applyPatch_modifies_source_json_doc() throws IOException { String actual = new String(JSONUtils.INSTANCE.applyPatch(patchJson, sourceJson)); assertThat(JSONUtils.INSTANCE.load(actual, JSONUtils.MAP_SUPPLIER), equalTo(JSONUtils.INSTANCE.load(expectedJson, JSONUtils.MAP_SUPPLIER))); }