You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2014/10/30 13:22:15 UTC
git commit: AMBARI-8035 - Alerts: Creating WEB Alert Definitions via
REST API Drops URI (jonathanhurley)
Repository: ambari
Updated Branches:
refs/heads/trunk 6e4c89bb0 -> f65a5af6c
AMBARI-8035 - Alerts: Creating WEB Alert Definitions via REST API Drops URI (jonathanhurley)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f65a5af6
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f65a5af6
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f65a5af6
Branch: refs/heads/trunk
Commit: f65a5af6c62c14c8442e7c3c6a88e07ac2a4a76e
Parents: 6e4c89b
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Wed Oct 29 23:25:53 2014 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Thu Oct 30 08:22:06 2014 -0400
----------------------------------------------------------------------
.../python/ambari_agent/alerts/metric_alert.py | 8 +-
.../python/ambari_agent/alerts/web_alert.py | 5 +-
.../AlertDefinitionResourceProvider.java | 149 +++++++++++++------
.../AlertDefinitionResourceProviderTest.java | 115 ++++++++++----
4 files changed, 200 insertions(+), 77 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/f65a5af6/ambari-agent/src/main/python/ambari_agent/alerts/metric_alert.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/alerts/metric_alert.py b/ambari-agent/src/main/python/ambari_agent/alerts/metric_alert.py
index e569bca..f43ad53 100644
--- a/ambari-agent/src/main/python/ambari_agent/alerts/metric_alert.py
+++ b/ambari-agent/src/main/python/ambari_agent/alerts/metric_alert.py
@@ -39,8 +39,12 @@ class MetricAlert(BaseAlert):
self.metric_info = JmxMetric(alert_source_meta['jmx'])
# extract any lookup keys from the URI structure
- self.uri_property_keys = self._lookup_uri_property_keys(alert_source_meta['uri'])
-
+ self.uri_property_keys = None
+ if 'uri' in alert_source_meta:
+ uri = alert_source_meta['uri']
+ self.uri_property_keys = self._lookup_uri_property_keys(uri)
+
+
def _collect(self):
if self.metric_info is None:
raise Exception("Could not determine result. Specific metric collector is not defined.")
http://git-wip-us.apache.org/repos/asf/ambari/blob/f65a5af6/ambari-agent/src/main/python/ambari_agent/alerts/web_alert.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/alerts/web_alert.py b/ambari-agent/src/main/python/ambari_agent/alerts/web_alert.py
index 03f2566..c967c8e 100644
--- a/ambari-agent/src/main/python/ambari_agent/alerts/web_alert.py
+++ b/ambari-agent/src/main/python/ambari_agent/alerts/web_alert.py
@@ -33,7 +33,10 @@ class WebAlert(BaseAlert):
super(WebAlert, self).__init__(alert_meta, alert_source_meta)
# extract any lookup keys from the URI structure
- self.uri_property_keys = self._lookup_uri_property_keys(alert_source_meta['uri'])
+ self.uri_property_keys = None
+ if 'uri' in alert_source_meta:
+ uri = alert_source_meta['uri']
+ self.uri_property_keys = self._lookup_uri_property_keys(uri)
def _collect(self):
http://git-wip-us.apache.org/repos/asf/ambari/blob/f65a5af6/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
index e1c0082..86e7b7e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
@@ -19,6 +19,7 @@ package org.apache.ambari.server.controller.internal;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
@@ -54,6 +55,7 @@ import org.apache.ambari.server.state.alert.SourceType;
import org.apache.commons.lang.StringUtils;
import com.google.gson.Gson;
+import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.inject.Inject;
import com.google.inject.Injector;
@@ -77,10 +79,6 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
protected static final String ALERT_DEF_SOURCE = "AlertDefinition/source";
protected static final String ALERT_DEF_SOURCE_TYPE = "AlertDefinition/source/type";
- protected static final String ALERT_DEF_SOURCE_REPORTING = "AlertDefinition/source/reporting";
- protected static final String ALERT_DEF_SOURCE_REPORTING_OK = "AlertDefinition/source/reporting/ok";
- protected static final String ALERT_DEF_SOURCE_REPORTING_WARNING = "AlertDefinition/source/reporting/warning";
- protected static final String ALERT_DEF_SOURCE_REPORTING_CRITICAL = "AlertDefinition/source/reporting/critical";
protected static final String ALERT_DEF_ACTION_RUN_NOW = "AlertDefinition/run_now";
@@ -429,67 +427,51 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
throw new IllegalArgumentException("Service name must be specified");
}
+ // on creation, source type is required
if (bCreate && null == sourceType) {
throw new IllegalArgumentException(String.format(
"Source type must be specified and one of %s",
EnumSet.allOf(SourceType.class)));
}
- // !!! Alert structures contain nested objects; reconstruct a valid
- // JSON from the flat, exploded properties so that a Source instance can
- // be properly persisted
- JsonObject source = new JsonObject();
- JsonObject reporting = new JsonObject();
- JsonObject reportingOk = new JsonObject();
- JsonObject reportingWarning = new JsonObject();
- JsonObject reportingCritical = new JsonObject();
+ // !!! The AlertDefinition "Source" field is a nested JSON object;
+ // build a JSON representation from the flat properties and then
+ // serialize that JSON object as a string
+ Map<String,JsonObject> jsonObjectMapping = new HashMap<String, JsonObject>();
+ // for every property in the request, if it's a source property, then
+ // add it to the JSON model
for (Entry<String, Object> entry : requestMap.entrySet()) {
- String propCat = PropertyHelper.getPropertyCategory(entry.getKey());
- String propName = PropertyHelper.getPropertyName(entry.getKey());
+ String propertyKey = entry.getKey();
- if (propCat.equals(ALERT_DEF) && "source".equals(propName)) {
- source.addProperty(propName, entry.getValue().toString());
+ // only handle "source" subproperties
+ if (!propertyKey.startsWith(ALERT_DEF_SOURCE)) {
+ continue;
}
- if (propCat.equals(ALERT_DEF_SOURCE)) {
- source.addProperty(propName, entry.getValue().toString());
- }
+ // gets a JSON object to add the property to; this will create the
+ // property and all of its parent properties recursively if necessary
+ JsonObject jsonObject = getJsonObjectMapping(ALERT_DEF_SOURCE,
+ jsonObjectMapping, propertyKey);
- if (propCat.equals(ALERT_DEF_SOURCE_REPORTING)) {
- reporting.addProperty(propName, entry.getValue().toString());
- }
+ String propertyName = PropertyHelper.getPropertyName(propertyKey);
+ Object entryValue = entry.getValue();
- if (propCat.equals(ALERT_DEF_SOURCE_REPORTING_OK)) {
- reportingOk.addProperty(propName, entry.getValue().toString());
- }
-
- if (propCat.equals(ALERT_DEF_SOURCE_REPORTING_WARNING)) {
- reportingWarning.addProperty(propName, entry.getValue().toString());
- }
-
- if (propCat.equals(ALERT_DEF_SOURCE_REPORTING_CRITICAL)) {
- reportingCritical.addProperty(propName, entry.getValue().toString());
+ if( entryValue instanceof Collection<?> ){
+ JsonElement jsonElement = gson.toJsonTree(entryValue);
+ jsonObject.add(propertyName, jsonElement);
+ } else {
+ if (entryValue instanceof Number) {
+ jsonObject.addProperty(propertyName, (Number) entryValue);
+ } else {
+ jsonObject.addProperty(propertyName, entryValue.toString());
+ }
}
}
- if (reportingOk.entrySet().size() > 0) {
- reporting.add("ok", reportingOk);
- }
-
- if (reportingWarning.entrySet().size() > 0) {
- reporting.add("warning", reportingWarning);
- }
-
- if (reportingCritical.entrySet().size() > 0) {
- reporting.add("critical", reportingCritical);
- }
-
- if (reporting.entrySet().size() > 0) {
- source.add("reporting", reporting);
- }
-
- if (bCreate && 0 == source.entrySet().size()) {
+ // "source" must be filled in when creating
+ JsonObject source = jsonObjectMapping.get(ALERT_DEF_SOURCE);
+ if (bCreate && (null == source || 0 == source.entrySet().size())) {
throw new IllegalArgumentException("Source must be specified");
}
@@ -540,6 +522,75 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
entity.setHash(UUID.randomUUID().toString());
}
+ /**
+ * Gets a {@link JsonObject} that the specified flattened property should be
+ * set on, creating all parent {@link JsonObject} instances as needed. This
+ * will turn {code AlertDefinition/source/reporting/critical/text} into
+ *
+ * <pre>
+ * AlertDefinition/source: {
+ * reporting: {
+ * critical: {
+ * text
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * Where the the following {@link JsonObject} instances are created:
+ *
+ * <pre>
+ * AlertDefinition/source
+ * Reporting
+ * Critical
+ * property 'text',
+ * property 'value',
+ * etc
+ * </pre>
+ *
+ * @param root
+ * the flattened property which will be considered the root.
+ * @param jsonObjectMapping
+ * a mapping of flattened property to {@link JsonObject}.
+ * @param propertyKey
+ * the key to get the {@link JsonObject} for.
+ * @return the {@link JsonObject} that cooresponds to the specified key.
+ */
+ private JsonObject getJsonObjectMapping(String root,
+ Map<String, JsonObject> jsonObjectMapping, String propertyKey) {
+
+ // if there is already a mapping for the key, return the mapping
+ if (jsonObjectMapping.containsKey(propertyKey)) {
+ return jsonObjectMapping.get(propertyKey);
+ }
+
+ if (root.equals(propertyKey)) {
+ JsonObject jsonRoot = jsonObjectMapping.get(root);
+ if (null == jsonRoot) {
+ jsonRoot = new JsonObject();
+ jsonObjectMapping.put(root, jsonRoot);
+ }
+
+ return jsonRoot;
+ }
+
+ String propertyCategory = PropertyHelper.getPropertyCategory(propertyKey);
+ JsonObject categoryJson = jsonObjectMapping.get(propertyCategory);
+
+ if (null == categoryJson) {
+ JsonObject parent = getJsonObjectMapping(root, jsonObjectMapping,
+ propertyCategory);
+
+ categoryJson = new JsonObject();
+ jsonObjectMapping.put(propertyCategory, categoryJson);
+
+ String categoryName = PropertyHelper.getPropertyName(propertyCategory);
+ parent.add(categoryName, categoryJson);
+ }
+
+ return categoryJson;
+ }
+
private Resource toResource(boolean isCollection, String clusterName,
AlertDefinitionEntity entity, Set<String> requestedIds) {
Resource resource = new ResourceImpl(Resource.Type.AlertDefinition);
http://git-wip-us.apache.org/repos/asf/ambari/blob/f65a5af6/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
index a82e8c4..7823994 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
@@ -55,6 +55,7 @@ import org.apache.ambari.server.state.Clusters;
import org.apache.ambari.server.state.alert.AlertDefinition;
import org.apache.ambari.server.state.alert.AlertDefinitionFactory;
import org.apache.ambari.server.state.alert.AlertDefinitionHash;
+import org.apache.ambari.server.state.alert.MetricSource;
import org.apache.ambari.server.state.alert.Scope;
import org.apache.ambari.server.state.alert.Source;
import org.apache.ambari.server.state.alert.SourceType;
@@ -193,7 +194,7 @@ public class AlertDefinitionResourceProviderTest {
Source source = getMockSource();
String okJson = source.getReporting().getOk().getText();
- Object reporting = r.getPropertyValue(AlertDefinitionResourceProvider.ALERT_DEF_SOURCE_REPORTING);
+ Object reporting = r.getPropertyValue("AlertDefinition/source/reporting");
Assert.assertTrue(reporting.toString().contains(okJson));
@@ -242,7 +243,7 @@ public class AlertDefinitionResourceProviderTest {
Assert.assertEquals("my_def",
resource.getPropertyValue(AlertDefinitionResourceProvider.ALERT_DEF_NAME));
- Map<String, String> reporting = (Map<String, String>) resource.getPropertyValue(AlertDefinitionResourceProvider.ALERT_DEF_SOURCE_REPORTING);
+ Map<String, String> reporting = (Map<String, String>) resource.getPropertyValue("AlertDefinition/source/reporting");
Assert.assertTrue(reporting.containsKey("ok"));
Assert.assertTrue(reporting.containsKey("critical"));
@@ -263,7 +264,8 @@ public class AlertDefinitionResourceProviderTest {
"my_def",
resource.getPropertyValue(AlertDefinitionResourceProvider.ALERT_DEF_NAME));
- reporting = (Map<String, String>) resource.getPropertyValue(AlertDefinitionResourceProvider.ALERT_DEF_SOURCE_REPORTING);
+ reporting = (Map<String, String>) resource.getPropertyValue("AlertDefinition/source/reporting");
+
Assert.assertNull(reporting);
}
@@ -291,8 +293,7 @@ public class AlertDefinitionResourceProviderTest {
replay(amc, clusters, cluster, dao, definitionHash);
Gson gson = m_factory.getGson();
- Source source = getMockSource();
- String sourceJson = gson.toJson(source);
+ MetricSource source = (MetricSource)getMockSource();
AlertDefinitionResourceProvider provider = createProvider(amc);
Map<String, Object> requestProps = new HashMap<String, Object>();
@@ -303,17 +304,42 @@ public class AlertDefinitionResourceProviderTest {
requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_SERVICE_NAME,
"HDFS");
- requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_SOURCE,
- sourceJson);
+ requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_LABEL,
+ "Mock Label (Create)");
requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_SOURCE_TYPE,
SourceType.METRIC.name());
- requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_LABEL,
- "Mock Label (Create)");
+ // JMX
+ requestProps.put("AlertDefinition/source/jmx/value",
+ source.getJmxInfo().getValue());
+ requestProps.put("AlertDefinition/source/jmx/property_list",
+ source.getJmxInfo().getPropertyList());
+
+ // URI
+ requestProps.put("AlertDefinition/source/uri/http",
+ source.getUri().getHttpUri());
+ requestProps.put("AlertDefinition/source/uri/https",
+ source.getUri().getHttpsUri());
+ requestProps.put("AlertDefinition/source/uri/https_property",
+ source.getUri().getHttpsProperty());
+ requestProps.put("AlertDefinition/source/uri/https_property_value",
+ source.getUri().getHttpsPropertyValue());
+
+ // reporting
+ requestProps.put("AlertDefinition/source/reporting/critical/text",
+ source.getReporting().getCritical().getText());
+ requestProps.put("AlertDefinition/source/reporting/critical/value",
+ source.getReporting().getCritical().getValue());
+ requestProps.put("AlertDefinition/source/reporting/ok/text",
+ source.getReporting().getOk().getText());
+ requestProps.put("AlertDefinition/source/reporting/warning/text",
+ source.getReporting().getWarning().getText());
+ requestProps.put("AlertDefinition/source/reporting/warning/value",
+ source.getReporting().getWarning().getValue());
- Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
+ Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
provider.createResources(request);
Assert.assertTrue(entityCapture.hasCaptured());
@@ -333,20 +359,30 @@ public class AlertDefinitionResourceProviderTest {
// verify Source
Assert.assertNotNull(entity.getSource());
- Source actualSource = gson.fromJson(entity.getSource(), Source.class);
+ MetricSource actualSource = gson.fromJson(entity.getSource(),
+ MetricSource.class);
+
Assert.assertNotNull(actualSource);
assertEquals(source.getReporting().getOk().getText(),
- source.getReporting().getOk().getText());
+ actualSource.getReporting().getOk().getText());
assertEquals(source.getReporting().getWarning().getText(),
- source.getReporting().getWarning().getText());
+ actualSource.getReporting().getWarning().getText());
assertEquals(source.getReporting().getCritical().getText(),
- source.getReporting().getCritical().getText());
+ actualSource.getReporting().getCritical().getText());
- verify(amc, clusters, cluster, dao);
+ Assert.assertNotNull(source.getUri().getHttpUri());
+ Assert.assertNotNull(source.getUri().getHttpsUri());
+
+ assertEquals(source.getUri().getHttpUri(),
+ actualSource.getUri().getHttpUri());
+
+ assertEquals(source.getUri().getHttpsUri(),
+ actualSource.getUri().getHttpsUri());
+ verify(amc, clusters, cluster, dao);
}
/**
@@ -354,8 +390,6 @@ public class AlertDefinitionResourceProviderTest {
*/
@Test
public void testUpdateResources() throws Exception {
- Gson gson = m_factory.getGson();
-
AmbariManagementController amc = createMock(AmbariManagementController.class);
Clusters clusters = createMock(Clusters.class);
Cluster cluster = createMock(Cluster.class);
@@ -376,8 +410,7 @@ public class AlertDefinitionResourceProviderTest {
replay(amc, clusters, cluster, dao, definitionHash);
- Source source = getMockSource();
- String sourceString = gson.toJson(source);
+ MetricSource source = (MetricSource) getMockSource();
Map<String, Object> requestProps = new HashMap<String, Object>();
requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_CLUSTER_NAME, "c1");
@@ -387,12 +420,37 @@ public class AlertDefinitionResourceProviderTest {
requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_SERVICE_NAME, "HDFS");
requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_SOURCE_TYPE, "METRIC");
- requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_SOURCE,
- sourceString);
-
requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_ENABLED,
Boolean.TRUE.toString());
+ // JMX
+ requestProps.put("AlertDefinition/source/jmx/value",
+ source.getJmxInfo().getValue());
+ requestProps.put("AlertDefinition/source/jmx/property_list",
+ source.getJmxInfo().getPropertyList());
+
+ // URI
+ requestProps.put("AlertDefinition/source/uri/http",
+ source.getUri().getHttpUri());
+ requestProps.put("AlertDefinition/source/uri/https",
+ source.getUri().getHttpsUri());
+ requestProps.put("AlertDefinition/source/uri/https_property",
+ source.getUri().getHttpsProperty());
+ requestProps.put("AlertDefinition/source/uri/https_property_value",
+ source.getUri().getHttpsPropertyValue());
+
+ // reporting
+ requestProps.put("AlertDefinition/source/reporting/critical/text",
+ source.getReporting().getCritical().getText());
+ requestProps.put("AlertDefinition/source/reporting/critical/value",
+ source.getReporting().getCritical().getValue());
+ requestProps.put("AlertDefinition/source/reporting/ok/text",
+ source.getReporting().getOk().getText());
+ requestProps.put("AlertDefinition/source/reporting/warning/text",
+ source.getReporting().getWarning().getText());
+ requestProps.put("AlertDefinition/source/reporting/warning/value",
+ source.getReporting().getWarning().getValue());
+
Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
AlertDefinitionResourceProvider provider = createProvider(amc);
@@ -430,8 +488,15 @@ public class AlertDefinitionResourceProviderTest {
requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_SERVICE_NAME, "HDFS");
requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_SOURCE_TYPE, "METRIC");
- requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_SOURCE,
- sourceString.replaceAll("CPU", "CPU2"));
+ // new URI
+ requestProps.put("AlertDefinition/source/uri/http",
+ source.getUri().getHttpUri() + "_foobarbaz");
+ requestProps.put("AlertDefinition/source/uri/https",
+ source.getUri().getHttpsUri() + "_foobarbaz");
+ requestProps.put("AlertDefinition/source/uri/https_property",
+ source.getUri().getHttpsProperty() + "_foobarbaz");
+ requestProps.put("AlertDefinition/source/uri/https_property_value",
+ source.getUri().getHttpsPropertyValue() + "_foobarbaz");
requestProps.put(AlertDefinitionResourceProvider.ALERT_DEF_ENABLED,
Boolean.FALSE.toString());
@@ -445,7 +510,7 @@ public class AlertDefinitionResourceProviderTest {
Assert.assertFalse(oldInterval.equals(entity.getScheduleInterval()));
Assert.assertFalse(oldEnabled == entity.getEnabled());
Assert.assertFalse(oldSource.equals(entity.getSource()));
- Assert.assertTrue(entity.getSource().contains("CPU2"));
+ Assert.assertTrue(entity.getSource().contains("_foobarbaz"));
verify(amc, clusters, cluster, dao);
}