You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by tb...@apache.org on 2015/04/14 01:24:03 UTC
ambari git commit: AMBARI-10424 - Views : Auto create (tbeerbower)
Repository: ambari
Updated Branches:
refs/heads/trunk 68dbaa64f -> 5a60fa18a
AMBARI-10424 - Views : Auto create (tbeerbower)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/5a60fa18
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/5a60fa18
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/5a60fa18
Branch: refs/heads/trunk
Commit: 5a60fa18a58ec1c38cdde625adb2b7e61eaf936b
Parents: 68dbaa6
Author: tbeerbower <tb...@hortonworks.com>
Authored: Mon Apr 13 19:23:28 2015 -0400
Committer: tbeerbower <tb...@hortonworks.com>
Committed: Mon Apr 13 19:23:48 2015 -0400
----------------------------------------------------------------------
.../apache/ambari/server/view/ViewRegistry.java | 128 +++++++++++++++-
.../view/configuration/AutoInstanceConfig.java | 65 ++++++++
.../server/view/configuration/ViewConfig.java | 15 ++
.../server/api/handlers/CreateHandlerTest.java | 5 +-
.../server/api/handlers/DeleteHandlerTest.java | 5 +-
.../server/api/handlers/UpdateHandlerTest.java | 5 +-
.../resources/BaseResourceDefinitionTest.java | 5 +-
.../internal/UpgradeResourceProviderTest.java | 7 +-
.../ambari/server/view/ViewRegistryTest.java | 153 ++++++++++++++++++-
.../configuration/AutoInstanceConfigTest.java | 116 ++++++++++++++
.../view/configuration/ViewConfigTest.java | 24 +++
ambari-views/src/main/resources/view.xsd | 37 +++++
12 files changed, 553 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
index 1ae1dfd..1564dd1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
@@ -19,6 +19,8 @@
package org.apache.ambari.server.view;
import com.google.common.collect.Sets;
+import com.google.common.eventbus.AllowConcurrentEvents;
+import com.google.common.eventbus.Subscribe;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
@@ -38,6 +40,8 @@ import org.apache.ambari.server.controller.AmbariSessionManager;
import org.apache.ambari.server.controller.ControllerModule;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.events.ServiceInstalledEvent;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
import org.apache.ambari.server.orm.dao.MemberDAO;
import org.apache.ambari.server.orm.dao.PrivilegeDAO;
import org.apache.ambari.server.orm.dao.ResourceDAO;
@@ -62,7 +66,9 @@ import org.apache.ambari.server.orm.entities.ViewResourceEntity;
import org.apache.ambari.server.security.SecurityHelper;
import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority;
import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.StackId;
import org.apache.ambari.server.utils.VersionUtils;
+import org.apache.ambari.server.view.configuration.AutoInstanceConfig;
import org.apache.ambari.server.view.configuration.EntityConfig;
import org.apache.ambari.server.view.configuration.InstanceConfig;
import org.apache.ambari.server.view.configuration.ParameterConfig;
@@ -257,7 +263,18 @@ public class ViewRegistry {
AmbariSessionManager ambariSessionManager;
- // ----- ViewRegistry ------------------------------------------------------
+ // ----- Constructors -----------------------------------------------------
+
+ /**
+ * Create the view registry.
+ */
+ @Inject
+ public ViewRegistry(AmbariEventPublisher publisher) {
+ publisher.register(this);
+ }
+
+
+// ----- ViewRegistry ------------------------------------------------------
/**
* Registry main method.
@@ -843,9 +860,104 @@ public class ViewRegistry {
return null;
}
+ /**
+ * Receive notification that a new service has been added to a cluster.
+ * </p>
+ * Used for view instance auto creation.
+ *
+ * @param event the service installed event
+ */
+ @Subscribe
+ @AllowConcurrentEvents
+ public void onAmbariEvent(ServiceInstalledEvent event) {
+
+ Clusters clusters = clustersProvider.get();
+ Long clusterId = event.getClusterId();
+
+ try {
+ org.apache.ambari.server.state.Cluster cluster = clusters.getClusterById(clusterId);
+ String clusterName = cluster.getClusterName();
+
+ StackId stackId = cluster.getCurrentStackVersion();
+ Set<String> serviceNames = cluster.getServices().keySet();
+
+ for (ViewEntity viewEntity : getDefinitions()) {
+
+ String viewName = viewEntity.getName();
+ ViewConfig viewConfig = viewEntity.getConfiguration();
+ AutoInstanceConfig autoConfig = viewConfig.getAutoInstance();
+
+ try {
+ if (checkAutoInstanceConfig(autoConfig, stackId, event.getServiceName(), serviceNames)) {
+
+ LOG.info("Auto creating instance of view " + viewName + " for cluster " + clusterName + ".");
+ ViewInstanceEntity viewInstanceEntity = createViewInstanceEntity(viewEntity, viewConfig, autoConfig);
+ viewInstanceEntity.setClusterHandle(clusterName);
+ installViewInstance(viewInstanceEntity);
+ }
+ } catch (Exception e) {
+ LOG.error("Can't auto create instance of view " + viewName + " for cluster " + clusterName +
+ ". Caught exception :" + e.getMessage(), e);
+ }
+ }
+ } catch (AmbariException e) {
+ LOG.warn("Unknown cluster id " + clusterId + ".");
+ }
+ }
+
+
// ----- helper methods ----------------------------------------------------
/**
+ * Determine whether a new view instance should be automatically created and associated with
+ * a cluster based on the given configuration and cluster state.
+ *
+ * @param autoConfig the view instance auto creation configuration
+ * @param stackId the stack id of the cluster
+ * @param serviceName the name of the service added which triggered this check
+ * @param serviceNames the set of service names of the cluster
+ *
+ * @return true if a new view instance should be created
+ */
+ private boolean checkAutoInstanceConfig(AutoInstanceConfig autoConfig, StackId stackId,
+ String serviceName, Set<String> serviceNames) {
+
+ if (autoConfig != null) {
+ List<String> autoCreateServices = autoConfig.getServices();
+
+ if (autoCreateServices != null && autoCreateServices.contains(serviceName) &&
+ serviceNames.containsAll(autoCreateServices)) {
+
+ String configStackId = autoConfig.getStackId();
+
+ if (configStackId != null) {
+ StackId id = new StackId(configStackId);
+
+ if (id.getStackName().equals(stackId.getStackName())) {
+
+ String stackVersion = stackId.getStackVersion();
+ String configStackVersion = id.getStackVersion();
+
+ // make sure that the configured stack version equals the cluster stack version (account for *)
+ int compVal = 0;
+
+ int index = configStackVersion.indexOf('*');
+ if (index == -1) {
+ compVal = VersionUtils.compareVersions(configStackVersion, stackVersion);
+ } else if (index > 0) {
+ String[] parts = configStackVersion.substring(0, index).split("\\.");
+ compVal = VersionUtils.compareVersions(configStackVersion, stackVersion, parts.length);
+ }
+
+ return compVal == 0;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
* Clear the registry.
*/
protected void clear() {
@@ -992,6 +1104,17 @@ public class ViewRegistry {
protected ViewInstanceEntity createViewInstanceDefinition(ViewConfig viewConfig, ViewEntity viewDefinition,
InstanceConfig instanceConfig)
throws ValidationException, ClassNotFoundException, SystemException {
+ ViewInstanceEntity viewInstanceDefinition = createViewInstanceEntity(viewDefinition, viewConfig, instanceConfig);
+ viewInstanceDefinition.validate(viewDefinition, Validator.ValidationContext.PRE_CREATE);
+
+ bindViewInstance(viewDefinition, viewInstanceDefinition);
+ return viewInstanceDefinition;
+ }
+
+ // create a view instance from the given configuration
+ private ViewInstanceEntity createViewInstanceEntity(ViewEntity viewDefinition, ViewConfig viewConfig,
+ InstanceConfig instanceConfig)
+ throws SystemException {
ViewInstanceEntity viewInstanceDefinition =
new ViewInstanceEntity(viewDefinition, instanceConfig);
@@ -1001,9 +1124,6 @@ public class ViewRegistry {
properties.put(propertyConfig.getKey(), propertyConfig.getValue());
}
setViewInstanceProperties(viewInstanceDefinition, properties, viewConfig, viewDefinition.getClassLoader());
- viewInstanceDefinition.validate(viewDefinition, Validator.ValidationContext.PRE_CREATE);
-
- bindViewInstance(viewDefinition, viewInstanceDefinition);
return viewInstanceDefinition;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/AutoInstanceConfig.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/AutoInstanceConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/AutoInstanceConfig.java
new file mode 100644
index 0000000..e837464
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/AutoInstanceConfig.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.view.configuration;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import java.util.List;
+
+/**
+ * View auto instance configuration.
+ * </p>
+ * Used by Ambari to automatically create an instance of a view and associate it with
+ * a cluster if the cluster's stack and services match those given in this configuration.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public class AutoInstanceConfig extends InstanceConfig {
+ /**
+ * The stack id.
+ */
+ @XmlElement(name="stack-id")
+ private String stackId;
+
+ /**
+ * The list of view instances.
+ */
+ @XmlElementWrapper
+ @XmlElement(name="service")
+ private List<String> services;
+
+ /**
+ * Get the stack id used for auto instance creation.
+ *
+ * @return the stack id
+ */
+ public String getStackId() {
+ return stackId;
+ }
+
+ /**
+ * Get the services used for auto instance creation.
+ *
+ * @return the services
+ */
+ public List<String> getServices() {
+ return services;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
index c617b7f..6164bb7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
@@ -131,6 +131,12 @@ public class ViewConfig {
private List<ResourceConfig> resources;
/**
+ * The view instance auto create configuration.
+ */
+ @XmlElement(name="auto-instance")
+ private AutoInstanceConfig autoInstance;
+
+ /**
* The list of view instances.
*/
@XmlElement(name="instance")
@@ -326,6 +332,15 @@ public class ViewConfig {
}
/**
+ * Get the configuration for the view instance auto create.
+ *
+ * @return the view instance auto create; null if no auto instance is specified
+ */
+ public AutoInstanceConfig getAutoInstance() {
+ return autoInstance;
+ }
+
+ /**
* Get the list of view instances.
*
* @return the list of view instances
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/CreateHandlerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/CreateHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/CreateHandlerTest.java
index 87c07c8..2b50064 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/CreateHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/CreateHandlerTest.java
@@ -28,6 +28,7 @@ import org.apache.ambari.server.api.services.persistence.PersistenceManager;
import org.apache.ambari.server.api.util.TreeNode;
import org.apache.ambari.server.controller.spi.RequestStatus;
import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
import org.apache.ambari.server.view.ViewRegistry;
import org.junit.Before;
import org.junit.Test;
@@ -44,7 +45,9 @@ public class CreateHandlerTest {
@Before
public void before() {
- ViewRegistry.initInstance(new ViewRegistry());
+ AmbariEventPublisher publisher = createNiceMock(AmbariEventPublisher.class);
+ replay(publisher);
+ ViewRegistry.initInstance(new ViewRegistry(publisher));
}
@Test
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/DeleteHandlerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/DeleteHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/DeleteHandlerTest.java
index 7e19129..4f053fd 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/DeleteHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/DeleteHandlerTest.java
@@ -31,6 +31,7 @@ import org.apache.ambari.server.api.util.TreeNode;
import org.apache.ambari.server.controller.spi.Predicate;
import org.apache.ambari.server.controller.spi.RequestStatus;
import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
import org.apache.ambari.server.view.ViewRegistry;
import org.junit.Before;
import org.junit.Test;
@@ -50,7 +51,9 @@ public class DeleteHandlerTest {
@Before
public void before() {
- ViewRegistry.initInstance(new ViewRegistry());
+ AmbariEventPublisher publisher = createNiceMock(AmbariEventPublisher.class);
+ replay(publisher);
+ ViewRegistry.initInstance(new ViewRegistry(publisher));
}
@Test
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java
index 5ef3e53..c88a0ec 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java
@@ -28,6 +28,7 @@ import org.apache.ambari.server.api.util.TreeNode;
import org.apache.ambari.server.controller.spi.Predicate;
import org.apache.ambari.server.controller.spi.RequestStatus;
import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
import org.apache.ambari.server.view.ViewRegistry;
import org.junit.Before;
import org.junit.Test;
@@ -44,7 +45,9 @@ public class UpdateHandlerTest {
@Before
public void before() {
- ViewRegistry.initInstance(new ViewRegistry());
+ AmbariEventPublisher publisher = createNiceMock(AmbariEventPublisher.class);
+ replay(publisher);
+ ViewRegistry.initInstance(new ViewRegistry(publisher));
}
@Test
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
index da3fe3f..3f64d9a 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
@@ -42,6 +42,7 @@ import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.ResourceProvider;
import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
import org.apache.ambari.server.state.Service;
import org.apache.ambari.server.view.ViewRegistry;
import org.junit.Assert;
@@ -62,7 +63,9 @@ public class BaseResourceDefinitionTest {
@Before
public void before() {
- ViewRegistry.initInstance(new ViewRegistry());
+ AmbariEventPublisher publisher = createNiceMock(AmbariEventPublisher.class);
+ replay(publisher);
+ ViewRegistry.initInstance(new ViewRegistry(publisher));
}
@Test
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
index baa885c..d2f7f80 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
@@ -17,7 +17,9 @@
*/
package org.apache.ambari.server.controller.internal;
+import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -44,6 +46,7 @@ import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.ResourceProvider;
import org.apache.ambari.server.controller.utilities.PredicateBuilder;
import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
import org.apache.ambari.server.orm.OrmTestHelper;
@@ -125,7 +128,9 @@ public class UpgradeResourceProviderTest {
upgradeDao = injector.getInstance(UpgradeDAO.class);
repoVersionDao = injector.getInstance(RepositoryVersionDAO.class);
- ViewRegistry.initInstance(new ViewRegistry());
+ AmbariEventPublisher publisher = createNiceMock(AmbariEventPublisher.class);
+ replay(publisher);
+ ViewRegistry.initInstance(new ViewRegistry(publisher));
RepositoryVersionEntity repoVersionEntity = new RepositoryVersionEntity();
repoVersionEntity.setDisplayName("My New Version 1");
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
index 3a57b1b..1b7c9a5 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
@@ -56,6 +56,8 @@ import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.events.ServiceInstalledEvent;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
import org.apache.ambari.server.orm.dao.MemberDAO;
import org.apache.ambari.server.orm.dao.PrivilegeDAO;
import org.apache.ambari.server.orm.dao.ResourceDAO;
@@ -76,6 +78,10 @@ import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceEntityTest;
import org.apache.ambari.server.security.SecurityHelper;
import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.StackId;
import org.apache.ambari.server.view.configuration.InstanceConfig;
import org.apache.ambari.server.view.configuration.InstanceConfigTest;
import org.apache.ambari.server.view.configuration.PropertyConfig;
@@ -162,6 +168,39 @@ public class ViewRegistryTest {
" </instance>\n" +
"</view>";
+ private static String AUTO_VIEW_XML = "<view>\n" +
+ " <name>MY_VIEW</name>\n" +
+ " <label>My View!</label>\n" +
+ " <version>1.0.0</version>\n" +
+ " <auto-instance>\n" +
+ " <name>AUTO-INSTANCE</name>\n" +
+ " <stack-id>HDP-2.0</stack-id>\n" +
+ " <services><service>HIVE</service><service>HDFS</service></services>\n" +
+ " </auto-instance>\n" +
+ "</view>";
+
+ private static String AUTO_VIEW_WILD_STACK_XML = "<view>\n" +
+ " <name>MY_VIEW</name>\n" +
+ " <label>My View!</label>\n" +
+ " <version>1.0.0</version>\n" +
+ " <auto-instance>\n" +
+ " <name>AUTO-INSTANCE</name>\n" +
+ " <stack-id>HDP-2.*</stack-id>\n" +
+ " <services><service>HIVE</service><service>HDFS</service></services>\n" +
+ " </auto-instance>\n" +
+ "</view>";
+
+ private static String AUTO_VIEW_BAD_STACK_XML = "<view>\n" +
+ " <name>MY_VIEW</name>\n" +
+ " <label>My View!</label>\n" +
+ " <version>1.0.0</version>\n" +
+ " <auto-instance>\n" +
+ " <name>AUTO-INSTANCE</name>\n" +
+ " <stack-id>HDP-2.5</stack-id>\n" +
+ " <services><service>HIVE</service><service>HDFS</service></services>\n" +
+ " </auto-instance>\n" +
+ "</view>";
+
// registry mocks
private static final ViewDAO viewDAO = createMock(ViewDAO.class);
private static final ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
@@ -174,15 +213,17 @@ public class ViewRegistryTest {
private static final Configuration configuration = createNiceMock(Configuration.class);
private static final ViewInstanceHandlerList handlerList = createNiceMock(ViewInstanceHandlerList.class);
private static final AmbariMetaInfo ambariMetaInfo = createNiceMock(AmbariMetaInfo.class);
+ private static final Clusters clusters = createNiceMock(Clusters.class);
@Before
public void resetGlobalMocks() {
ViewRegistry.initInstance(getRegistry(viewDAO, viewInstanceDAO, userDAO, memberDAO, privilegeDAO,
- resourceDAO, resourceTypeDAO, securityHelper, handlerList, null, null, ambariMetaInfo));
+ resourceDAO, resourceTypeDAO, securityHelper, handlerList, null, null, ambariMetaInfo, clusters));
reset(viewDAO, resourceDAO, viewInstanceDAO, userDAO, memberDAO,
- privilegeDAO, resourceTypeDAO, securityHelper, configuration, handlerList, ambariMetaInfo);
+ privilegeDAO, resourceTypeDAO, securityHelper, configuration, handlerList, ambariMetaInfo,
+ clusters);
}
@@ -1265,6 +1306,42 @@ public class ViewRegistryTest {
}
@Test
+ public void testOnAmbariEventServiceCreation() throws Exception {
+ Set<String> serviceNames = new HashSet<String>();
+ serviceNames.add("HDFS");
+ serviceNames.add("HIVE");
+
+ testOnAmbariEventServiceCreation(AUTO_VIEW_XML, serviceNames, true);
+ }
+
+ @Test
+ public void testOnAmbariEventServiceCreation_widcardStackVersion() throws Exception {
+ Set<String> serviceNames = new HashSet<String>();
+ serviceNames.add("HDFS");
+ serviceNames.add("HIVE");
+
+ testOnAmbariEventServiceCreation(AUTO_VIEW_WILD_STACK_XML, serviceNames, true);
+ }
+
+ @Test
+ public void testOnAmbariEventServiceCreation_mismatchStackVersion() throws Exception {
+ Set<String> serviceNames = new HashSet<String>();
+ serviceNames.add("HDFS");
+ serviceNames.add("HIVE");
+
+ testOnAmbariEventServiceCreation(AUTO_VIEW_BAD_STACK_XML, serviceNames, false);
+ }
+
+ @Test
+ public void testOnAmbariEventServiceCreation_missingClusterService() throws Exception {
+ Set<String> serviceNames = new HashSet<String>();
+ serviceNames.add("STORM");
+ serviceNames.add("HIVE");
+
+ testOnAmbariEventServiceCreation(AUTO_VIEW_XML, serviceNames, false);
+ }
+
+ @Test
public void testIncludeDefinitionForNoApiAuthentication() {
ViewRegistry registry = ViewRegistry.getInstance();
ViewEntity viewEntity = createNiceMock(ViewEntity.class);
@@ -1599,8 +1676,27 @@ public class ViewRegistryTest {
ViewExtractor viewExtractor,
ViewArchiveUtility archiveUtility,
AmbariMetaInfo ambariMetaInfo) {
+ return getRegistry(viewDAO, viewInstanceDAO, userDAO, memberDAO, privilegeDAO, resourceDAO, resourceTypeDAO,
+ securityHelper, handlerList, viewExtractor, archiveUtility, ambariMetaInfo, null);
+ }
+
+ public static ViewRegistry getRegistry(ViewDAO viewDAO, ViewInstanceDAO viewInstanceDAO,
+ UserDAO userDAO, MemberDAO memberDAO,
+ PrivilegeDAO privilegeDAO, ResourceDAO resourceDAO,
+ ResourceTypeDAO resourceTypeDAO, SecurityHelper securityHelper,
+ ViewInstanceHandlerList handlerList,
+ ViewExtractor viewExtractor,
+ ViewArchiveUtility archiveUtility,
+ AmbariMetaInfo ambariMetaInfo,
+ Clusters clusters) {
+
+
+
+ AmbariEventPublisher publisher = createNiceMock(AmbariEventPublisher.class);
+ replay(publisher);
- ViewRegistry instance = new ViewRegistry();
+
+ ViewRegistry instance = new ViewRegistry(publisher);
instance.viewDAO = viewDAO;
instance.resourceDAO = resourceDAO;
@@ -1624,6 +1720,13 @@ public class ViewRegistryTest {
}
};
+ final Clusters finalClusters = clusters;
+ instance.clustersProvider = new Provider<Clusters>() {
+ @Override
+ public Clusters get() {
+ return finalClusters;
+ }
+ };
return instance;
}
@@ -1655,4 +1758,48 @@ public class ViewRegistryTest {
registry.bindViewInstance(viewDefinition, viewInstanceDefinition);
return viewInstanceDefinition;
}
+
+ private void testOnAmbariEventServiceCreation(String xml, Set<String> serviceNames, boolean success) throws Exception {
+ ViewConfig config = ViewConfigTest.getConfig(xml);
+
+ ViewEntity viewDefinition = ViewEntityTest.getViewEntity(config);
+
+ ViewRegistry registry = ViewRegistry.getInstance();
+ registry.addDefinition(viewDefinition);
+
+ ViewInstanceEntity viewInstanceEntity = createNiceMock(ViewInstanceEntity.class);
+ Cluster cluster = createNiceMock(Cluster.class);
+ Service service = createNiceMock(Service.class);
+
+ Map<String, Service> serviceMap = new HashMap<String, Service>();
+
+ for (String serviceName : serviceNames) {
+ serviceMap.put(serviceName, service);
+ }
+
+ StackId stackId = new StackId("HDP-2.0");
+
+ expect(clusters.getClusterById(99L)).andReturn(cluster);
+ expect(cluster.getClusterName()).andReturn("c1").anyTimes();
+ expect(cluster.getCurrentStackVersion()).andReturn(stackId).anyTimes();
+ expect(cluster.getServices()).andReturn(serviceMap).anyTimes();
+
+ Capture<ViewInstanceEntity> viewInstanceCapture = new Capture<ViewInstanceEntity>();
+
+ expect(viewInstanceDAO.merge(capture(viewInstanceCapture))).andReturn(viewInstanceEntity).anyTimes();
+ expect(viewInstanceDAO.findByName("MY_VIEW{1.0.0}", "AUTO-INSTANCE")).andReturn(viewInstanceEntity).anyTimes();
+
+ replay(securityHelper, configuration, viewInstanceDAO, clusters, cluster, viewInstanceEntity);
+
+
+ ServiceInstalledEvent event = new ServiceInstalledEvent(99L, "HDP", "2.0", "HIVE");
+
+ registry.onAmbariEvent(event);
+
+ if (success) {
+ Assert.assertEquals(viewInstanceCapture.getValue(), registry.getInstanceDefinition("MY_VIEW", "1.0.0", "AUTO-INSTANCE"));
+ }
+
+ verify(securityHelper, configuration, viewInstanceDAO, clusters, cluster, viewInstanceEntity);
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/AutoInstanceConfigTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/AutoInstanceConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/AutoInstanceConfigTest.java
new file mode 100644
index 0000000..fde5376
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/AutoInstanceConfigTest.java
@@ -0,0 +1,116 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.view.configuration;
+
+import junit.framework.Assert;
+import org.junit.Test;
+
+import javax.xml.bind.JAXBException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+/**
+ * AutoInstanceConfig tests.
+ */
+public class AutoInstanceConfigTest {
+
+
+ private static String VIEW_XML = "<view>\n" +
+ " <name>MY_VIEW</name>\n" +
+ " <label>My View!</label>\n" +
+ " <description>Description</description>" +
+ " <version>1.0.0</version>\n" +
+ " <system>true</system>\n" +
+ " <icon64>/this/is/the/icon/url/icon64.png</icon64>\n" +
+ " <icon>/this/is/the/icon/url/icon.png</icon>\n" +
+ " <validator-class>org.apache.ambari.server.view.configuration.ViewConfigTest$MyValidator</validator-class>" +
+ " <masker-class>org.apache.ambari.server.view.DefaultMasker</masker-class>" +
+ " <parameter>\n" +
+ " <name>p1</name>\n" +
+ " <description>Parameter 1.</description>\n" +
+ " <label>Label 1.</label>\n" +
+ " <placeholder>Placeholder 1.</placeholder>\n" +
+ " <required>true</required>\n" +
+ " </parameter>\n" +
+ " <parameter>\n" +
+ " <name>p2</name>\n" +
+ " <description>Parameter 2.</description>\n" +
+ " <default-value>Default value 1.</default-value>\n" +
+ " <cluster-config>hdfs-site/dfs.namenode.http-address</cluster-config>\n" +
+ " <required>false</required>\n" +
+ " <masked>true</masked>" +
+ " </parameter>\n" +
+ " <auto-instance>\n" +
+ " <name>INSTANCE1</name>\n" +
+ " <label>My Instance 1!</label>\n" +
+ " <description>This is a description.</description>\n" +
+ " <icon64>/this/is/the/icon/url/instance_1_icon64.png</icon64>\n" +
+ " <icon>/this/is/the/icon/url/instance_1_icon.png</icon>\n" +
+ " <property>\n" +
+ " <key>p1</key>\n" +
+ " <value>v1-1</value>\n" +
+ " </property>\n" +
+ " <property>\n" +
+ " <key>p2</key>\n" +
+ " <value>v2-1</value>\n" +
+ " </property>\n" +
+ " <stack-id>HDP-2.0</stack-id>\n" +
+ " <services><service>HIVE</service><service>HDFS</service></services>\n" +
+ " </auto-instance>\n" +
+ "</view>";
+
+ @Test
+ public void testGetName() throws Exception {
+ AutoInstanceConfig config = getAutoInstanceConfigs(VIEW_XML);
+
+ Assert.assertEquals("INSTANCE1", config.getName());
+ }
+
+ @Test
+ public void testDescription() throws Exception {
+ AutoInstanceConfig config = getAutoInstanceConfigs(VIEW_XML);
+
+ assertEquals("This is a description.", config.getDescription());
+ }
+
+ @Test
+ public void testGetStackId() throws Exception {
+ AutoInstanceConfig config = getAutoInstanceConfigs(VIEW_XML);
+
+ assertEquals("HDP-2.0", config.getStackId());
+ }
+
+ @Test
+ public void testGetServices() throws Exception {
+ AutoInstanceConfig config = getAutoInstanceConfigs(VIEW_XML);
+ List<String> serviceNames = config.getServices();
+
+ assertEquals(2, serviceNames.size());
+ assertTrue(serviceNames.contains("HIVE"));
+ assertTrue(serviceNames.contains("HDFS"));
+ }
+
+ public static AutoInstanceConfig getAutoInstanceConfigs(String xml) throws JAXBException {
+ ViewConfig config = ViewConfigTest.getConfig(xml);
+ return config.getAutoInstance();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java
index 1875238..beb8bde 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java
@@ -87,6 +87,23 @@ public class ViewConfigTest {
" <provider-class>org.apache.ambari.server.view.configuration.ViewConfigTest$MyResourceProvider</provider-class>\n" +
" <service-class>org.apache.ambari.server.view.configuration.ViewConfigTest$MyResourceService</service-class>\n" +
" </resource>\n" +
+ " <auto-instance>\n" +
+ " <name>AUTO-INSTANCE</name>\n" +
+ " <label>My Instance 1!</label>\n" +
+ " <description>This is a description.</description>\n" +
+ " <icon64>/this/is/the/icon/url/instance_1_icon64.png</icon64>\n" +
+ " <icon>/this/is/the/icon/url/instance_1_icon.png</icon>\n" +
+ " <property>\n" +
+ " <key>p1</key>\n" +
+ " <value>v1-1</value>\n" +
+ " </property>\n" +
+ " <property>\n" +
+ " <key>p2</key>\n" +
+ " <value>v2-1</value>\n" +
+ " </property>\n" +
+ " <stack-id>HDP-2.0</stack-id>\n" +
+ " <services><service>HIVE</service><service>HDFS</service></services>\n" +
+ " </auto-instance>\n" +
" <instance>\n" +
" <name>INSTANCE1</name>\n" +
" <label>My Instance 1!</label>\n" +
@@ -233,6 +250,13 @@ public class ViewConfigTest {
}
@Test
+ public void testGetAutoInstance() throws Exception {
+ ViewConfig config = getConfig(xml);
+ AutoInstanceConfig instance = config.getAutoInstance();
+ Assert.assertEquals("AUTO-INSTANCE", instance.getName());
+ }
+
+ @Test
public void testGetInstances() throws Exception {
ViewConfig config = getConfig(xml);
List<InstanceConfig> instances = config.getInstances();
http://git-wip-us.apache.org/repos/asf/ambari/blob/5a60fa18/ambari-views/src/main/resources/view.xsd
----------------------------------------------------------------------
diff --git a/ambari-views/src/main/resources/view.xsd b/ambari-views/src/main/resources/view.xsd
index b5ed669..37737c1 100644
--- a/ambari-views/src/main/resources/view.xsd
+++ b/ambari-views/src/main/resources/view.xsd
@@ -219,6 +219,38 @@
</xs:sequence>
</xs:complexType>
+ <xs:complexType name="ServiceType">
+ <xs:annotation>
+ <xs:documentation>Defines a persistence entity used by the view.</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element type="xs:string" name="service" minOccurs="1" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>The name of a service required to auto create an instance of this view.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="AutoInstanceType">
+ <xs:complexContent>
+ <xs:extension base="InstanceType">
+ <xs:sequence>
+ <xs:element name="stack-id" type="xs:string" minOccurs="1" maxOccurs="1">
+ <xs:annotation>
+ <xs:documentation>The stack id required to auto create an instance of this view. The wildcard character '*' is supported (e.g. 'HDP-2.*').</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element type="ServiceType" name="services" minOccurs="1" maxOccurs="1">
+ <xs:annotation>
+ <xs:documentation>The services required to auto create an instance of this view.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
<xs:element name="view">
<xs:annotation>
<xs:documentation>Defines a view.</xs:documentation>
@@ -310,6 +342,11 @@
<xs:documentation>Defines the persistence entities used by the view.</xs:documentation>
</xs:annotation>
</xs:element>
+ <xs:element type="AutoInstanceType" name="auto-instance" minOccurs="0" maxOccurs="1">
+ <xs:annotation>
+ <xs:documentation>Defines an auto create instance of the view.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
<xs:element type="InstanceType" name="instance" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Defines a static instance of the view.</xs:documentation>