diff --git a/src/main/java/org/opensearch/agent/tools/SearchAnomalyDetectorsTool.java b/src/main/java/org/opensearch/agent/tools/SearchAnomalyDetectorsTool.java index 2bbbcfa7..22c3d0db 100644 --- a/src/main/java/org/opensearch/agent/tools/SearchAnomalyDetectorsTool.java +++ b/src/main/java/org/opensearch/agent/tools/SearchAnomalyDetectorsTool.java @@ -245,7 +245,7 @@ private void processHits(Map hitsAsMap, ActionListener sb.append("{"); sb.append("id=").append(hit.getId()).append(","); sb.append("name=").append(hit.getSourceAsMap().get("name")).append(","); - sb.append("type=").append(hit.getSourceAsMap().get("type")).append(","); + sb.append("type=").append(hit.getSourceAsMap().get("detector_type")).append(","); sb.append("description=").append(hit.getSourceAsMap().get("description")).append(","); sb.append("index=").append(hit.getSourceAsMap().get("indices")).append(","); sb.append("lastUpdateTime=").append(hit.getSourceAsMap().get("last_update_time")); diff --git a/src/main/java/org/opensearch/agent/tools/SearchMonitorsTool.java b/src/main/java/org/opensearch/agent/tools/SearchMonitorsTool.java index bbb9aaa7..304d598d 100644 --- a/src/main/java/org/opensearch/agent/tools/SearchMonitorsTool.java +++ b/src/main/java/org/opensearch/agent/tools/SearchMonitorsTool.java @@ -19,10 +19,7 @@ import org.opensearch.client.Client; import org.opensearch.client.node.NodeClient; import org.opensearch.commons.alerting.AlertingPluginInterface; -import org.opensearch.commons.alerting.action.GetMonitorRequest; -import org.opensearch.commons.alerting.action.GetMonitorResponse; import org.opensearch.commons.alerting.action.SearchMonitorRequest; -import org.opensearch.commons.alerting.model.Monitor; import org.opensearch.commons.alerting.model.ScheduledJob; import org.opensearch.core.action.ActionListener; import org.opensearch.index.query.BoolQueryBuilder; @@ -35,7 +32,6 @@ import org.opensearch.ml.common.spi.tools.Parser; import org.opensearch.ml.common.spi.tools.Tool; import org.opensearch.ml.common.spi.tools.ToolAnnotation; -import org.opensearch.rest.RestRequest; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.search.sort.SortOrder; @@ -102,89 +98,73 @@ public void run(Map parameters, ActionListener listener) ? Integer.parseInt(parameters.get("startIndex")) : 0; - // If a monitor ID is specified, all other params will be ignored. Simply return the monitor details based on that ID - // via the get monitor transport action + List mustList = new ArrayList(); if (monitorId != null) { - GetMonitorRequest getMonitorRequest = new GetMonitorRequest(monitorId, 1L, RestRequest.Method.GET, null); - ActionListener getMonitorListener = ActionListener.wrap(response -> { - Monitor monitor = response.getMonitor(); - processGetMonitorHit(monitor, listener); - }, e -> { - // System index isn't initialized by default, so ignore such errors. Alerting plugin does not return the - // standard IndexNotFoundException so we parse the message instead - if (e.getMessage().contains("Configured indices are not found")) { - processGetMonitorHit(null, listener); - } else { - log.error("Failed to get monitor.", e); - listener.onFailure(e); - } - }); - AlertingPluginInterface.INSTANCE.getMonitor((NodeClient) client, getMonitorRequest, getMonitorListener); - } else { - List mustList = new ArrayList(); - if (monitorName != null) { - mustList.add(new TermQueryBuilder("monitor.name.keyword", monitorName)); - } - if (monitorNamePattern != null) { - mustList.add(new WildcardQueryBuilder("monitor.name.keyword", monitorNamePattern)); - } - if (enabled != null) { - mustList.add(new TermQueryBuilder("monitor.enabled", enabled)); + mustList.add(new TermQueryBuilder("_id", monitorId)); + } + if (monitorName != null) { + mustList.add(new TermQueryBuilder("monitor.name.keyword", monitorName)); + } + if (monitorNamePattern != null) { + mustList.add(new WildcardQueryBuilder("monitor.name.keyword", monitorNamePattern)); + } + if (enabled != null) { + mustList.add(new TermQueryBuilder("monitor.enabled", enabled)); + } + if (hasTriggers != null) { + NestedQueryBuilder nestedTriggerQuery = new NestedQueryBuilder( + "monitor.triggers", + new ExistsQueryBuilder("monitor.triggers"), + ScoreMode.None + ); + + BoolQueryBuilder triggerQuery = new BoolQueryBuilder(); + if (hasTriggers) { + triggerQuery.must(nestedTriggerQuery); + } else { + triggerQuery.mustNot(nestedTriggerQuery); } - if (hasTriggers != null) { - NestedQueryBuilder nestedTriggerQuery = new NestedQueryBuilder( - "monitor.triggers", - new ExistsQueryBuilder("monitor.triggers"), - ScoreMode.None + mustList.add(triggerQuery); + } + if (indices != null) { + mustList + .add( + new NestedQueryBuilder( + "monitor.inputs", + new WildcardQueryBuilder("monitor.inputs.search.indices", indices), + ScoreMode.None + ) ); + } - BoolQueryBuilder triggerQuery = new BoolQueryBuilder(); - if (hasTriggers) { - triggerQuery.must(nestedTriggerQuery); - } else { - triggerQuery.mustNot(nestedTriggerQuery); - } - mustList.add(triggerQuery); - } - if (indices != null) { - mustList - .add( - new NestedQueryBuilder( - "monitor.inputs", - new WildcardQueryBuilder("monitor.inputs.search.indices", indices), - ScoreMode.None - ) - ); + BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); + boolQueryBuilder.must().addAll(mustList); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder() + .query(boolQueryBuilder) + .size(size) + .from(startIndex) + .sort(sortString, sortOrder); + + SearchRequest searchRequest = new SearchRequest().source(searchSourceBuilder).indices(ScheduledJob.SCHEDULED_JOBS_INDEX); + SearchMonitorRequest searchMonitorRequest = new SearchMonitorRequest(searchRequest); + + ActionListener searchMonitorListener = ActionListener.wrap(response -> { + List hits = Arrays.asList(response.getHits().getHits()); + Map hitsAsMap = hits.stream().collect(Collectors.toMap(SearchHit::getId, hit -> hit)); + processHits(hitsAsMap, listener); + + }, e -> { + // System index isn't initialized by default, so ignore such errors. Alerting plugin does not return the + // standard IndexNotFoundException so we parse the message instead + if (e.getMessage().contains("Configured indices are not found")) { + processHits(Collections.emptyMap(), listener); + } else { + log.error("Failed to search monitors.", e); + listener.onFailure(e); } + }); + AlertingPluginInterface.INSTANCE.searchMonitors((NodeClient) client, searchMonitorRequest, searchMonitorListener); - BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); - boolQueryBuilder.must().addAll(mustList); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder() - .query(boolQueryBuilder) - .size(size) - .from(startIndex) - .sort(sortString, sortOrder); - - SearchRequest searchRequest = new SearchRequest().source(searchSourceBuilder).indices(ScheduledJob.SCHEDULED_JOBS_INDEX); - SearchMonitorRequest searchMonitorRequest = new SearchMonitorRequest(searchRequest); - - ActionListener searchMonitorListener = ActionListener.wrap(response -> { - List hits = Arrays.asList(response.getHits().getHits()); - Map hitsAsMap = hits.stream().collect(Collectors.toMap(SearchHit::getId, hit -> hit)); - processHits(hitsAsMap, listener); - - }, e -> { - // System index isn't initialized by default, so ignore such errors. Alerting plugin does not return the - // standard IndexNotFoundException so we parse the message instead - if (e.getMessage().contains("Configured indices are not found")) { - processHits(Collections.emptyMap(), listener); - } else { - log.error("Failed to search monitors.", e); - listener.onFailure(e); - } - }); - AlertingPluginInterface.INSTANCE.searchMonitors((NodeClient) client, searchMonitorRequest, searchMonitorListener); - } } @Override @@ -201,13 +181,14 @@ private void processHits(Map hitsAsMap, ActionListener StringBuilder sb = new StringBuilder(); sb.append("Monitors=["); for (SearchHit hit : hitsAsMap.values()) { + Map monitorAsMap = (Map) hit.getSourceAsMap().get("monitor"); sb.append("{"); sb.append("id=").append(hit.getId()).append(","); - sb.append("name=").append(hit.getSourceAsMap().get("name")).append(","); - sb.append("type=").append(hit.getSourceAsMap().get("type")).append(","); - sb.append("enabled=").append(hit.getSourceAsMap().get("enabled")).append(","); - sb.append("enabledTime=").append(hit.getSourceAsMap().get("enabled_time")).append(","); - sb.append("lastUpdateTime=").append(hit.getSourceAsMap().get("last_update_time")); + sb.append("name=").append(monitorAsMap.get("name")).append(","); + sb.append("type=").append(monitorAsMap.get("type")).append(","); + sb.append("enabled=").append(monitorAsMap.get("enabled")).append(","); + sb.append("enabledTime=").append(monitorAsMap.get("enabled_time")).append(","); + sb.append("lastUpdateTime=").append(monitorAsMap.get("last_update_time")); sb.append("}"); } sb.append("]"); @@ -215,25 +196,6 @@ private void processHits(Map hitsAsMap, ActionListener listener.onResponse((T) sb.toString()); } - private void processGetMonitorHit(Monitor monitor, ActionListener listener) { - StringBuilder sb = new StringBuilder(); - if (monitor != null) { - sb.append("Monitors=["); - sb.append("{"); - sb.append("id=").append(monitor.getId()).append(","); - sb.append("name=").append(monitor.getName()).append(","); - sb.append("type=").append(monitor.getType()).append(","); - sb.append("enabled=").append(monitor.getEnabled()).append(","); - sb.append("enabledTime=").append(monitor.getEnabledTime().toEpochMilli()).append(","); - sb.append("lastUpdateTime=").append(monitor.getLastUpdateTime().toEpochMilli()); - sb.append("}]"); - sb.append("TotalMonitors=1"); - } else { - sb.append("Monitors=[]TotalMonitors=0"); - } - listener.onResponse((T) sb.toString()); - } - /** * Factory for the {@link SearchMonitorsTool} */ diff --git a/src/test/java/org/opensearch/agent/tools/SearchAnomalyDetectorsToolTests.java b/src/test/java/org/opensearch/agent/tools/SearchAnomalyDetectorsToolTests.java index c4f0c293..13213f85 100644 --- a/src/test/java/org/opensearch/agent/tools/SearchAnomalyDetectorsToolTests.java +++ b/src/test/java/org/opensearch/agent/tools/SearchAnomalyDetectorsToolTests.java @@ -116,7 +116,7 @@ public void testRunWithSingleAnomalyDetector() throws Exception { XContentBuilder content = XContentBuilder.builder(XContentType.JSON.xContent()); content.startObject(); content.field("name", testDetector.getName()); - content.field("type", testDetector.getDetectorType()); + content.field("detector_type", testDetector.getDetectorType()); content.field("description", testDetector.getDescription()); content.field("indices", testDetector.getIndices().get(0)); content.field("last_update_time", testDetector.getLastUpdateTime().toEpochMilli()); diff --git a/src/test/java/org/opensearch/agent/tools/SearchMonitorsToolTests.java b/src/test/java/org/opensearch/agent/tools/SearchMonitorsToolTests.java index 72338fec..4c5a690f 100644 --- a/src/test/java/org/opensearch/agent/tools/SearchMonitorsToolTests.java +++ b/src/test/java/org/opensearch/agent/tools/SearchMonitorsToolTests.java @@ -35,7 +35,6 @@ import org.opensearch.client.IndicesAdminClient; import org.opensearch.client.node.NodeClient; import org.opensearch.common.xcontent.XContentType; -import org.opensearch.commons.alerting.action.GetMonitorResponse; import org.opensearch.commons.alerting.model.CronSchedule; import org.opensearch.commons.alerting.model.DataSources; import org.opensearch.commons.alerting.model.Monitor; @@ -96,29 +95,15 @@ public void setup() { @Test public void testRunWithNoMonitors() throws Exception { Tool tool = SearchMonitorsTool.Factory.getInstance().create(Collections.emptyMap()); - - SearchHit[] hits = new SearchHit[0]; - - TotalHits totalHits = new TotalHits(hits.length, TotalHits.Relation.EQUAL_TO); - - SearchResponse getMonitorsResponse = new SearchResponse( - new SearchResponseSections(new SearchHits(hits, totalHits, 0), new Aggregations(new ArrayList<>()), null, false, null, null, 0), - null, - 0, - 0, - 0, - 0, - null, - null - ); - String expectedResponseStr = String.format("Monitors=[]TotalMonitors=%d", hits.length); + SearchResponse searchMonitorsResponse = getEmptySearchMonitorsResponse(); + String expectedResponseStr = "Monitors=[]TotalMonitors=0"; @SuppressWarnings("unchecked") ActionListener listener = Mockito.mock(ActionListener.class); doAnswer((invocation) -> { ActionListener responseListener = invocation.getArgument(2); - responseListener.onResponse(getMonitorsResponse); + responseListener.onResponse(searchMonitorsResponse); return null; }).when(nodeClient).execute(any(ActionType.class), any(), any()); @@ -132,21 +117,15 @@ public void testRunWithNoMonitors() throws Exception { public void testRunWithMonitorId() throws Exception { Tool tool = SearchMonitorsTool.Factory.getInstance().create(Collections.emptyMap()); - GetMonitorResponse getMonitorResponse = new GetMonitorResponse( - testMonitor.getId(), - 1L, - 2L, - 0L, - testMonitor, - Collections.emptyList() - ); + SearchResponse searchMonitorsResponse = getSearchMonitorsResponse(testMonitor); String expectedResponseStr = getExpectedResponseString(testMonitor); + @SuppressWarnings("unchecked") ActionListener listener = Mockito.mock(ActionListener.class); doAnswer((invocation) -> { - ActionListener responseListener = invocation.getArgument(2); - responseListener.onResponse(getMonitorResponse); + ActionListener responseListener = invocation.getArgument(2); + responseListener.onResponse(searchMonitorsResponse); return null; }).when(nodeClient).execute(any(ActionType.class), any(), any()); @@ -160,15 +139,15 @@ public void testRunWithMonitorId() throws Exception { public void testRunWithMonitorIdNotFound() throws Exception { Tool tool = SearchMonitorsTool.Factory.getInstance().create(Collections.emptyMap()); - GetMonitorResponse responseWithNullMonitor = new GetMonitorResponse(testMonitor.getId(), 1L, 2L, 0L, null, Collections.emptyList()); - String expectedResponseStr = String.format("Monitors=[]TotalMonitors=0"); + SearchResponse searchMonitorsResponse = getEmptySearchMonitorsResponse(); + String expectedResponseStr = "Monitors=[]TotalMonitors=0"; @SuppressWarnings("unchecked") ActionListener listener = Mockito.mock(ActionListener.class); doAnswer((invocation) -> { - ActionListener responseListener = invocation.getArgument(2); - responseListener.onResponse(responseWithNullMonitor); + ActionListener responseListener = invocation.getArgument(2); + responseListener.onResponse(searchMonitorsResponse); return null; }).when(nodeClient).execute(any(ActionType.class), any(), any()); @@ -182,29 +161,7 @@ public void testRunWithMonitorIdNotFound() throws Exception { public void testRunWithSingleMonitor() throws Exception { Tool tool = SearchMonitorsTool.Factory.getInstance().create(Collections.emptyMap()); - XContentBuilder content = XContentBuilder.builder(XContentType.JSON.xContent()); - content.startObject(); - content.field("name", testMonitor.getName()); - content.field("type", testMonitor.getType()); - content.field("enabled", Boolean.toString(testMonitor.getEnabled())); - content.field("enabled_time", Long.toString(testMonitor.getEnabledTime().toEpochMilli())); - content.field("last_update_time", Long.toString(testMonitor.getLastUpdateTime().toEpochMilli())); - content.endObject(); - SearchHit[] hits = new SearchHit[1]; - hits[0] = new SearchHit(0, testMonitor.getId(), null, null).sourceRef(BytesReference.bytes(content)); - - TotalHits totalHits = new TotalHits(hits.length, TotalHits.Relation.EQUAL_TO); - - SearchResponse getMonitorsResponse = new SearchResponse( - new SearchResponseSections(new SearchHits(hits, totalHits, 0), new Aggregations(new ArrayList<>()), null, false, null, null, 0), - null, - 0, - 0, - 0, - 0, - null, - null - ); + SearchResponse searchMonitorsResponse = getSearchMonitorsResponse(testMonitor); String expectedResponseStr = getExpectedResponseString(testMonitor); @SuppressWarnings("unchecked") @@ -212,7 +169,7 @@ public void testRunWithSingleMonitor() throws Exception { doAnswer((invocation) -> { ActionListener responseListener = invocation.getArgument(2); - responseListener.onResponse(getMonitorsResponse); + responseListener.onResponse(searchMonitorsResponse); return null; }).when(nodeClient).execute(any(ActionType.class), any(), any()); @@ -254,6 +211,50 @@ public void testValidate() { assertTrue(tool.validate(nullParams)); } + private SearchResponse getSearchMonitorsResponse(Monitor monitor) throws Exception { + XContentBuilder content = XContentBuilder.builder(XContentType.JSON.xContent()); + content + .startObject() + .startObject("monitor") + .field("name", monitor.getName()) + .field("type", monitor.getType()) + .field("enabled", Boolean.toString(monitor.getEnabled())) + .field("enabled_time", Long.toString(monitor.getEnabledTime().toEpochMilli())) + .field("last_update_time", Long.toString(monitor.getLastUpdateTime().toEpochMilli())) + .endObject() + .endObject(); + SearchHit[] hits = new SearchHit[1]; + hits[0] = new SearchHit(0, monitor.getId(), null, null).sourceRef(BytesReference.bytes(content)); + + TotalHits totalHits = new TotalHits(hits.length, TotalHits.Relation.EQUAL_TO); + + return new SearchResponse( + new SearchResponseSections(new SearchHits(hits, totalHits, 0), new Aggregations(new ArrayList<>()), null, false, null, null, 0), + null, + 0, + 0, + 0, + 0, + null, + null + ); + } + + private SearchResponse getEmptySearchMonitorsResponse() throws Exception { + SearchHit[] hits = new SearchHit[0]; + TotalHits totalHits = new TotalHits(hits.length, TotalHits.Relation.EQUAL_TO); + return new SearchResponse( + new SearchResponseSections(new SearchHits(hits, totalHits, 0), new Aggregations(new ArrayList<>()), null, false, null, null, 0), + null, + 0, + 0, + 0, + 0, + null, + null + ); + } + private String getExpectedResponseString(Monitor testMonitor) { return String .format( diff --git a/src/test/java/org/opensearch/integTest/BaseAgentToolsIT.java b/src/test/java/org/opensearch/integTest/BaseAgentToolsIT.java index 993e2b08..21b2a8d4 100644 --- a/src/test/java/org/opensearch/integTest/BaseAgentToolsIT.java +++ b/src/test/java/org/opensearch/integTest/BaseAgentToolsIT.java @@ -115,6 +115,13 @@ protected String deployModel(String modelId) { return parseFieldFromResponse(response, MLTask.TASK_ID_FIELD).toString(); } + protected String indexMonitor(String monitorAsJsonString) { + Response response = makeRequest(client(), "POST", "_plugins/_alerting/monitors", null, monitorAsJsonString, null); + + assertEquals(RestStatus.CREATED, RestStatus.fromCode(response.getStatusLine().getStatusCode())); + return parseFieldFromResponse(response, "_id").toString(); + } + @SneakyThrows protected Map waitTaskComplete(String taskId) { for (int i = 0; i < MAX_TASK_RESULT_QUERY_TIME_IN_SECOND; i++) { diff --git a/src/test/java/org/opensearch/integTest/SearchMonitorsToolIT.java b/src/test/java/org/opensearch/integTest/SearchMonitorsToolIT.java index c94bf8e8..2ed9c726 100644 --- a/src/test/java/org/opensearch/integTest/SearchMonitorsToolIT.java +++ b/src/test/java/org/opensearch/integTest/SearchMonitorsToolIT.java @@ -9,16 +9,23 @@ import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.json.JSONObject; import org.junit.After; import org.junit.Before; +import org.junit.jupiter.api.BeforeEach; import lombok.SneakyThrows; +import lombok.extern.log4j.Log4j2; +@Log4j2 public class SearchMonitorsToolIT extends BaseAgentToolsIT { private String registerAgentRequestBody; - private static final String monitorId = "foo-id"; private static final String monitorName = "foo-name"; + private static final String monitorName2 = "bar-name"; @Before @SneakyThrows @@ -37,6 +44,12 @@ public void setUp() { ); } + @BeforeEach + @SneakyThrows + public void prepareTest() { + deleteSystemIndices(); + } + @After @SneakyThrows public void tearDown() { @@ -47,12 +60,86 @@ public void tearDown() { @SneakyThrows public void testSearchMonitorsToolInFlowAgent_withNoSystemIndex() { - deleteSystemIndices(); String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{\"monitorName\": \"" + monitorName + "\"}}"; String result = executeAgent(agentId, agentInput); assertEquals("Monitors=[]TotalMonitors=0", result); } - // TODO: Add IT to test against sample monitor data + @SneakyThrows + public void testSearchMonitorsToolInFlowAgent_searchById() { + String monitorId = indexMonitor(getMonitorJsonString(monitorName, true)); + + String agentId = createAgent(registerAgentRequestBody); + String agentInput = "{\"parameters\":{\"monitorId\": \"" + monitorId + "\"}}"; + + String result = executeAgent(agentId, agentInput); + assertTrue(result.contains(String.format("name=%s", monitorName))); + assertTrue(result.contains("TotalMonitors=1")); + } + + @SneakyThrows + public void testSearchMonitorsToolInFlowAgent_singleMonitor_noFilter() { + indexMonitor(getMonitorJsonString(monitorName, true)); + + String agentId = createAgent(registerAgentRequestBody); + String agentInput = "{\"parameters\":{}}"; + String result = executeAgent(agentId, agentInput); + assertTrue(result.contains(String.format("name=%s", monitorName))); + assertTrue(result.contains("TotalMonitors=1")); + } + + @SneakyThrows + public void testSearchMonitorsToolInFlowAgent_singleMonitor_filter() { + String agentId = createAgent(registerAgentRequestBody); + String agentInput = "{\"parameters\":{\"monitorId\": \"" + "foo-id" + "\"}}"; + String result = executeAgent(agentId, agentInput); + assertTrue(result.contains("TotalMonitors=0")); + } + + @SneakyThrows + public void testSearchMonitorsToolInFlowAgent_multipleMonitors_noFilter() { + indexMonitor(getMonitorJsonString(monitorName, true)); + indexMonitor(getMonitorJsonString(monitorName2, false)); + + String agentId = createAgent(registerAgentRequestBody); + String agentInput = "{\"parameters\":{}}"; + String result = executeAgent(agentId, agentInput); + assertTrue(result.contains(String.format("name=%s", monitorName))); + assertTrue(result.contains(String.format("name=%s", monitorName2))); + assertTrue(result.contains("enabled=true")); + assertTrue(result.contains("enabled=false")); + assertTrue(result.contains("TotalMonitors=2")); + } + + @SneakyThrows + public void testSearchMonitorsToolInFlowAgent_multipleMonitors_filter() { + indexMonitor(getMonitorJsonString(monitorName, true)); + indexMonitor(getMonitorJsonString(monitorName2, false)); + + String agentId = createAgent(registerAgentRequestBody); + String agentInput = "{\"parameters\":{\"monitorName\": \"" + monitorName + "\"}}"; + String result = executeAgent(agentId, agentInput); + assertTrue(result.contains(String.format("name=%s", monitorName))); + assertFalse(result.contains(String.format("name=%s", monitorName2))); + assertTrue(result.contains("enabled=true")); + assertTrue(result.contains("TotalMonitors=1")); + } + + // Helper fn to create the JSON string to use in a REST request body when indexing a monitor + private String getMonitorJsonString(String monitorName, boolean enabled) { + JSONObject jsonObj = new JSONObject(); + jsonObj.put("type", "monitor"); + jsonObj.put("name", monitorName); + jsonObj.put("enabled", String.valueOf(enabled)); + jsonObj.put("inputs", Collections.emptyList()); + jsonObj.put("triggers", Collections.emptyList()); + Map scheduleMap = new HashMap(); + Map periodMap = new HashMap(); + periodMap.put("interval", 5); + periodMap.put("unit", "MINUTES"); + scheduleMap.put("period", periodMap); + jsonObj.put("schedule", scheduleMap); + return jsonObj.toString(); + } }