You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by js...@apache.org on 2014/02/03 16:40:42 UTC
[2/2] git commit: AMBARI-4467. Create new /blueprints REST endpoint.
AMBARI-4467. Create new /blueprints REST endpoint.
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/5f464316
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/5f464316
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/5f464316
Branch: refs/heads/trunk
Commit: 5f464316237c2a1661602eaa230f197221aae271
Parents: 6372db8
Author: John Speidel <js...@hortonworks.com>
Authored: Wed Jan 29 20:57:27 2014 -0500
Committer: John Speidel <js...@hortonworks.com>
Committed: Mon Feb 3 09:36:57 2014 -0500
----------------------------------------------------------------------
.../resources/BlueprintResourceDefinition.java | 45 +++
.../resources/ResourceInstanceFactoryImpl.java | 4 +
.../server/api/services/BlueprintService.java | 138 +++++++
.../ambari/server/controller/AmbariServer.java | 3 +
.../AbstractControllerResourceProvider.java | 8 +-
.../internal/BlueprintResourceProvider.java | 370 +++++++++++++++++++
.../internal/DefaultProviderModule.java | 2 +
.../ambari/server/controller/spi/Resource.java | 4 +-
.../ambari/server/orm/dao/BlueprintDAO.java | 109 ++++++
.../server/orm/entities/BlueprintEntity.java | 128 +++++++
.../orm/entities/HostGroupComponentEntity.java | 129 +++++++
.../entities/HostGroupComponentEntityPK.java | 114 ++++++
.../server/orm/entities/HostGroupEntity.java | 149 ++++++++
.../server/orm/entities/HostGroupEntityPK.java | 88 +++++
.../main/resources/Ambari-DDL-MySQL-CREATE.sql | 5 +
.../main/resources/Ambari-DDL-Oracle-CREATE.sql | 5 +
.../resources/Ambari-DDL-Postgres-CREATE.sql | 10 +
.../src/main/resources/META-INF/persistence.xml | 3 +
.../src/main/resources/key_properties.json | 5 +-
.../src/main/resources/properties.json | 16 +-
.../upgrade/ddl/Ambari-DDL-MySQL-UPGRADE.sql | 8 +
.../upgrade/ddl/Ambari-DDL-Oracle-UPGRADE.sql | 9 +-
.../ddl/Ambari-DDL-Postgres-UPGRADE-1.3.0.sql | 12 +
.../BlueprintResourceDefinitionTest.java | 53 +++
.../api/services/BlueprintServiceTest.java | 104 ++++++
.../internal/BlueprintResourceProviderTest.java | 290 +++++++++++++++
.../ambari/server/orm/dao/BlueprintDAOTest.java | 152 ++++++++
.../orm/entities/BlueprintEntityTest.java | 62 ++++
.../entities/HostGroupComponentEntityTest.java | 58 +++
.../orm/entities/HostGroupEntityTest.java | 69 ++++
30 files changed, 2141 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BlueprintResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BlueprintResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BlueprintResourceDefinition.java
new file mode 100644
index 0000000..7e81a8f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BlueprintResourceDefinition.java
@@ -0,0 +1,45 @@
+/**
+ * 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.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+
+/**
+ * Blueprint resource definition.
+ */
+public class BlueprintResourceDefinition extends BaseResourceDefinition {
+ /**
+ * Constructor.
+ *
+ */
+ public BlueprintResourceDefinition() {
+ super(Resource.Type.Blueprint);
+ }
+
+ @Override
+ public String getPluralName() {
+ return "blueprints";
+ }
+
+ @Override
+ public String getSingularName() {
+ return "blueprint";
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index 7dcaccb..aeb46e1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -204,6 +204,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
resourceDefinition = new ViewInstanceResourceDefinition(subResourceDefinitions);
break;
+ case Blueprint:
+ resourceDefinition = new BlueprintResourceDefinition();
+ break;
+
default:
throw new IllegalArgumentException("Unsupported resource type: " + type);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/api/services/BlueprintService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/BlueprintService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/BlueprintService.java
new file mode 100644
index 0000000..2d13ca7
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/BlueprintService.java
@@ -0,0 +1,138 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.Collections;
+
+/**
+ * Service responsible for handling REST requests for the /blueprints endpoint.
+ * This blueprint resource is a blueprint template meaning that it doesn't contain
+ * any cluster specific information. Updates are not permitted as blueprints are
+ * immutable.
+ */
+@Path("/blueprints/")
+public class BlueprintService extends BaseService {
+
+ /**
+ * Handles: GET /blueprints
+ * Get all blueprints.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @return blueprint collection resource representation
+ */
+ @GET
+ @Produces("text/plain")
+ public Response getBlueprints(@Context HttpHeaders headers, @Context UriInfo ui) {
+ return handleRequest(headers, null, ui, Request.Type.GET, createBlueprintResource(null));
+ }
+
+ /**
+ * Handles: GET /blueprints/{blueprintID}
+ * Get a specific blueprint.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param blueprintName blueprint id
+ * @return blueprint instance representation
+ */
+ @GET
+ @Path("{blueprintName}")
+ @Produces("text/plain")
+ public Response getBlueprint(@Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("blueprintName") String blueprintName) {
+
+ return handleRequest(headers, null, ui, Request.Type.GET, createBlueprintResource(blueprintName));
+ }
+
+ /**
+ * Handles: POST /blueprints/{blueprintID}
+ * Create a specific blueprint.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param blueprintName blueprint id
+ * @return information regarding the created blueprint
+ */
+ @POST
+ @Path("{blueprintName}")
+ @Produces("text/plain")
+ public Response createBlueprint(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("blueprintName") String blueprintName) {
+
+ return handleRequest(headers, body, ui, Request.Type.POST, createBlueprintResource(blueprintName));
+ }
+
+ /**
+ * Handles: DELETE /blueprints/{blueprintID}
+ * Delete a specific blueprint.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param blueprintName blueprint name
+ * @return information regarding the deleted blueprint
+ */
+ @DELETE
+ @Path("{blueprintName}")
+ @Produces("text/plain")
+ public Response deleteBlueprint(@Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("blueprintName") String blueprintName) {
+
+ return handleRequest(headers, null, ui, Request.Type.DELETE, createBlueprintResource(blueprintName));
+ }
+
+ /**
+ * Handles: DELETE /blueprints
+ * Delete a set of blueprints that match a predicate.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @return information regarding the deleted blueprint
+ */
+ @DELETE
+ @Produces("text/plain")
+ public Response deleteBlueprints(@Context HttpHeaders headers, @Context UriInfo ui) {
+ return handleRequest(headers, null, ui, Request.Type.DELETE, createBlueprintResource(null));
+ }
+
+ /**
+ * Create a blueprint resource instance.
+ *
+ * @param blueprintName blueprint name
+ *
+ * @return a blueprint resource instance
+ */
+ ResourceInstance createBlueprintResource(String blueprintName) {
+ return createResource(Resource.Type.Blueprint,
+ Collections.singletonMap(Resource.Type.Blueprint, blueprintName));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 75b6cb1..faaf0ee 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -42,10 +42,12 @@ import org.apache.ambari.server.bootstrap.BootStrapImpl;
import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.controller.internal.AbstractControllerResourceProvider;
+import org.apache.ambari.server.controller.internal.BlueprintResourceProvider;
import org.apache.ambari.server.controller.internal.StackDefinedPropertyProvider;
import org.apache.ambari.server.controller.nagios.NagiosPropertyProvider;
import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.orm.PersistenceType;
+import org.apache.ambari.server.orm.dao.BlueprintDAO;
import org.apache.ambari.server.orm.dao.MetainfoDAO;
import org.apache.ambari.server.orm.entities.MetainfoEntity;
import org.apache.ambari.server.resources.ResourceManager;
@@ -478,6 +480,7 @@ public class AmbariServer {
StackDefinedPropertyProvider.init(injector);
NagiosPropertyProvider.init(injector);
AbstractControllerResourceProvider.init(injector.getInstance(ResourceProviderFactory.class));
+ BlueprintResourceProvider.init(injector.getInstance(BlueprintDAO.class));
}
public static void main(String[] args) throws Exception {
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index c66ae65..880b13e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -141,10 +141,10 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
}
/**
- * Extracting given query_paramater value from the predicate
- * @param queryParameterId
- * @param predicate
- * @return
+ * Extracting given query_parameter value from the predicate
+ * @param queryParameterId query parameter id
+ * @param predicate predicate
+ * @return the query parameter
*/
protected static Object getQueryParameterValue(String queryParameterId, Predicate predicate) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
new file mode 100644
index 0000000..832f788
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
@@ -0,0 +1,370 @@
+/**
+ * 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.controller.internal;
+
+import com.google.inject.Inject;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.DuplicateResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.dao.BlueprintDAO;
+import org.apache.ambari.server.orm.entities.BlueprintEntity;
+import org.apache.ambari.server.orm.entities.HostGroupComponentEntity;
+import org.apache.ambari.server.orm.entities.HostGroupEntity;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Resource Provider for Blueprint resources.
+ */
+public class BlueprintResourceProvider extends AbstractResourceProvider {
+
+ // ----- Property ID constants ---------------------------------------------
+
+ // Blueprints
+ protected static final String BLUEPRINT_NAME_PROPERTY_ID =
+ PropertyHelper.getPropertyId("Blueprints", "blueprint_name");
+ protected static final String STACK_NAME_PROPERTY_ID =
+ PropertyHelper.getPropertyId("Blueprints", "stack_name");
+ protected static final String STACK_VERSION_PROPERTY_ID =
+ PropertyHelper.getPropertyId("Blueprints", "stack_version");
+
+ // Host Groups
+ protected static final String HOST_GROUP_PROPERTY_ID = "host_groups";
+ protected static final String HOST_GROUP_NAME_PROPERTY_ID = "name";
+ protected static final String HOST_GROUP_CARDINALITY_PROPERTY_ID = "cardinality";
+
+ // Host Group Components
+ protected static final String COMPONENT_PROPERTY_ID ="components";
+ protected static final String COMPONENT_NAME_PROPERTY_ID ="name";
+
+ // Primary Key Fields
+ private static Set<String> pkPropertyIds =
+ new HashSet<String>(Arrays.asList(new String[]{
+ BLUEPRINT_NAME_PROPERTY_ID}));
+
+ /**
+ * Blueprint data access object.
+ */
+ private static BlueprintDAO dao;
+
+
+ // ----- Constructors ----------------------------------------------------
+
+ /**
+ * Create a new resource provider for the given management controller.
+ *
+ * @param propertyIds the property ids
+ * @param keyPropertyIds the key property ids
+ */
+ BlueprintResourceProvider(Set<String> propertyIds, Map<Resource.Type, String> keyPropertyIds) {
+ super(propertyIds, keyPropertyIds);
+ }
+
+ /**
+ * Static initialization of DAO.
+ *
+ * @param blueprintDAO blueprint data access object
+ */
+ @Inject
+ public static void init(BlueprintDAO blueprintDAO) {
+ dao = blueprintDAO;
+ }
+
+
+ // ----- ResourceProvider ------------------------------------------------
+
+ @Override
+ protected Set<String> getPKPropertyIds() {
+ return pkPropertyIds;
+ }
+
+ @Override
+ public RequestStatus createResources(Request request)
+ throws SystemException, UnsupportedPropertyException,
+ ResourceAlreadyExistsException, NoSuchParentResourceException {
+
+ for (Map<String, Object> properties : request.getProperties()) {
+ createResources(getCreateCommand(properties));
+ }
+ notifyCreate(Resource.Type.Blueprint, request);
+
+ return getRequestStatus(null);
+ }
+
+ @Override
+ public Set<Resource> getResources(Request request, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException,
+ NoSuchResourceException, NoSuchParentResourceException {
+
+ List<BlueprintEntity> results = null;
+ boolean applyPredicate = false;
+
+ if (predicate != null) {
+ Set<Map<String, Object>> requestProps = getPropertyMaps(predicate);
+ if (requestProps.size() == 1 ) {
+ String name = (String) requestProps.iterator().next().get(
+ BLUEPRINT_NAME_PROPERTY_ID);
+
+ if (name != null) {
+ BlueprintEntity entity = dao.findByName(name);
+ results = entity == null ? Collections.<BlueprintEntity>emptyList() :
+ Collections.singletonList(entity);
+ }
+ }
+ }
+
+ if (results == null) {
+ applyPredicate = true;
+ results = dao.findAll();
+ }
+
+ Set<Resource> resources = new HashSet<Resource>();
+ for (BlueprintEntity entity : results) {
+ Resource resource = toResource(entity, getRequestPropertyIds(request, predicate));
+ if (predicate == null || ! applyPredicate || predicate.evaluate(resource)) {
+ resources.add(resource);
+ }
+ }
+
+ if (predicate != null && resources.isEmpty()) {
+ throw new NoSuchResourceException(
+ "The requested resource doesn't exist: Blueprint not found, " + predicate);
+ }
+
+ return resources;
+ }
+
+ @Override
+ public RequestStatus updateResources(Request request, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException,
+ NoSuchResourceException, NoSuchParentResourceException {
+
+ // no-op, blueprints are immutable
+ //todo: meaningful error message
+ return null;
+ }
+
+ @Override
+ public RequestStatus deleteResources(Predicate predicate)
+ throws SystemException, UnsupportedPropertyException,
+ NoSuchResourceException, NoSuchParentResourceException {
+
+ //TODO (jspeidel): Revisit concurrency control
+ Set<Resource> setResources = getResources(
+ new RequestImpl(null, null, null, null), predicate);
+
+ for (final Resource resource : setResources) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Deleting Blueprint, name=" +
+ resource.getPropertyValue(BLUEPRINT_NAME_PROPERTY_ID));
+ }
+ modifyResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ dao.remove(toEntity(resource));
+ return null;
+ }
+ });
+ }
+
+ notifyDelete(Resource.Type.Blueprint, predicate);
+ return getRequestStatus(null);
+ }
+
+
+ // ----- Instance Methods ------------------------------------------------
+
+ /**
+ * Create a resource instance from a blueprint entity.
+ *
+ * @param entity blueprint entity
+ * @param requestedIds requested id's
+ *
+ * @return a new resource instance for the given blueprint entity
+ */
+ protected Resource toResource(BlueprintEntity entity, Set<String> requestedIds) {
+ Resource resource = new ResourceImpl(Resource.Type.Blueprint);
+ setResourceProperty(resource, BLUEPRINT_NAME_PROPERTY_ID, entity.getBlueprintName(), requestedIds);
+ setResourceProperty(resource, STACK_NAME_PROPERTY_ID, entity.getStackName(), requestedIds);
+ setResourceProperty(resource, STACK_VERSION_PROPERTY_ID, entity.getStackVersion(), requestedIds);
+
+ List<Map<String, Object>> listGroupProps = new ArrayList<Map<String, Object>>();
+ Collection<HostGroupEntity> hostGroups = entity.getHostGroups();
+ for (HostGroupEntity hostGroup : hostGroups) {
+ Map<String, Object> mapGroupProps = new HashMap<String, Object>();
+ mapGroupProps.put(HOST_GROUP_NAME_PROPERTY_ID, hostGroup.getName());
+ listGroupProps.add(mapGroupProps);
+ mapGroupProps.put(HOST_GROUP_CARDINALITY_PROPERTY_ID, hostGroup.getCardinality());
+
+ List<Map<String, String>> listComponentProps = new ArrayList<Map<String, String>>();
+ Collection<HostGroupComponentEntity> components = hostGroup.getComponents();
+ for (HostGroupComponentEntity component : components) {
+ Map<String, String> mapComponentProps = new HashMap<String, String>();
+ mapComponentProps.put(COMPONENT_NAME_PROPERTY_ID, component.getName());
+ listComponentProps.add(mapComponentProps);
+ }
+ mapGroupProps.put(COMPONENT_PROPERTY_ID, listComponentProps);
+ }
+
+ setResourceProperty(resource, HOST_GROUP_PROPERTY_ID, listGroupProps, requestedIds);
+
+ return resource;
+ }
+
+ /**
+ * Convert a resource to a blueprint entity.
+ *
+ * @param resource the resource to convert
+ * @return a new blueprint entity
+ */
+ protected BlueprintEntity toEntity(Resource resource) {
+ BlueprintEntity entity = new BlueprintEntity();
+ entity.setBlueprintName((String) resource.getPropertyValue(BLUEPRINT_NAME_PROPERTY_ID));
+ entity.setStackName((String) resource.getPropertyValue(STACK_NAME_PROPERTY_ID));
+ entity.setStackVersion((String) resource.getPropertyValue(STACK_VERSION_PROPERTY_ID));
+
+ Collection<HostGroupEntity> blueprintHostGroups = new ArrayList<HostGroupEntity>();
+ entity.setHostGroups(blueprintHostGroups);
+
+ Collection<Map<String, Object>> hostGroupProps = (Collection<Map<String, Object>>)
+ resource.getPropertyValue(HOST_GROUP_PROPERTY_ID);
+
+ for (Map<String, Object> properties : hostGroupProps) {
+ HostGroupEntity group = new HostGroupEntity();
+ group.setName((String) properties.get(BlueprintResourceProvider.HOST_GROUP_NAME_PROPERTY_ID));
+ group.setBlueprintEntity(entity);
+ group.setBlueprintName(entity.getBlueprintName());
+ group.setCardinality((String) properties.get(HOST_GROUP_CARDINALITY_PROPERTY_ID));
+
+ Collection<HostGroupComponentEntity> hostGroupComponents = new ArrayList<HostGroupComponentEntity>();
+ group.setComponents(hostGroupComponents);
+
+ List<Map<String, String>> listComponents = (List<Map<String, String>>)
+ properties.get(BlueprintResourceProvider.COMPONENT_PROPERTY_ID);
+
+ for (Map<String, String> componentProperties : listComponents) {
+ HostGroupComponentEntity component = new HostGroupComponentEntity();
+ component.setName(componentProperties.get(COMPONENT_NAME_PROPERTY_ID));
+ component.setBlueprintName(entity.getBlueprintName());
+ component.setHostGroupEntity(group);
+ component.setHostGroupName((String) properties.get(HOST_GROUP_NAME_PROPERTY_ID));
+
+ hostGroupComponents.add(component);
+ }
+ blueprintHostGroups.add(group);
+ }
+
+ return entity;
+ }
+
+ /**
+ * Convert a map of properties to a blueprint entity.
+ *
+ * @param properties property map
+ * @return new blueprint entity
+ */
+ protected BlueprintEntity toEntity(Map<String, Object> properties) {
+ String name = (String) properties.get(BLUEPRINT_NAME_PROPERTY_ID);
+ if (name == null || name.isEmpty()) {
+ throw new IllegalArgumentException("Blueprint name must be provided");
+ }
+
+ BlueprintEntity blueprint = new BlueprintEntity();
+ blueprint.setBlueprintName(name);
+ blueprint.setStackName((String) properties.get(STACK_NAME_PROPERTY_ID));
+ blueprint.setStackVersion((String) properties.get(STACK_VERSION_PROPERTY_ID));
+
+ Collection<HostGroupEntity> blueprintHostGroups = new ArrayList<HostGroupEntity>();
+ blueprint.setHostGroups(blueprintHostGroups);
+
+ HashSet<HashMap<String, Object>> setHostGroups =
+ (HashSet<HashMap<String, Object>>) properties.get(HOST_GROUP_PROPERTY_ID);
+
+ for (HashMap<String, Object> hostGroupProperties : setHostGroups) {
+ HostGroupEntity group = new HostGroupEntity();
+ group.setName((String) hostGroupProperties.get(HOST_GROUP_NAME_PROPERTY_ID));
+ group.setBlueprintEntity(blueprint);
+ group.setBlueprintName(name);
+ group.setCardinality((String) hostGroupProperties.get(HOST_GROUP_CARDINALITY_PROPERTY_ID));
+
+ Collection<HostGroupComponentEntity> components = new ArrayList<HostGroupComponentEntity>();
+ group.setComponents(components);
+
+ HashSet<HashMap<String, String>> setComponents =
+ (HashSet<HashMap<String, String>>) hostGroupProperties.get(COMPONENT_PROPERTY_ID);
+ for (HashMap<String, String> componentProperties : setComponents) {
+ HostGroupComponentEntity component = new HostGroupComponentEntity();
+ component.setName(componentProperties.get(COMPONENT_NAME_PROPERTY_ID));
+ component.setBlueprintName(name);
+ component.setHostGroupEntity(group);
+ component.setHostGroupName((String) hostGroupProperties.get(HOST_GROUP_NAME_PROPERTY_ID));
+
+ components.add(component);
+ }
+ blueprintHostGroups.add(group);
+ }
+
+ return blueprint;
+ }
+
+ /**
+ * Create a create command with all properties set.
+ *
+ * @param properties properties to be applied to blueprint
+ *
+ * @return a new create command
+ */
+ private Command<Void> getCreateCommand(final Map<String, Object> properties) {
+ return new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ BlueprintEntity blueprint = toEntity(properties);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Creating Blueprint, name=" + blueprint.getBlueprintName());
+ }
+
+ if (dao.findByName(blueprint.getBlueprintName()) != null) {
+ throw new DuplicateResourceException(
+ "Attempted to create a Blueprint which already exists, blueprint_name=" +
+ blueprint.getBlueprintName());
+ }
+ dao.create(blueprint);
+ return null;
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
index e8765e4..4f25638 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
@@ -65,6 +65,8 @@ public class DefaultProviderModule extends AbstractProviderModule {
return new ViewResourceProvider();
case ViewInstance:
return new ViewInstanceResourceProvider();
+ case Blueprint:
+ return new BlueprintResourceProvider(propertyIds, keyPropertyIds);
default:
return AbstractControllerResourceProvider.getResourceProvider(type, propertyIds,
keyPropertyIds, managementController);
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index 52f0cdf..56f9d49 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -103,7 +103,8 @@ public interface Resource {
RootServiceComponent,
RootServiceHostComponent,
View,
- ViewInstance;
+ ViewInstance,
+ Blueprint;
/**
* Get the {@link Type} that corresponds to this InternalType.
@@ -168,6 +169,7 @@ public interface Resource {
public static final Type RootServiceHostComponent = InternalType.RootServiceHostComponent.getType();
public static final Type View = InternalType.View.getType();
public static final Type ViewInstance = InternalType.ViewInstance.getType();
+ public static final Type Blueprint = InternalType.Blueprint.getType();
/**
* The type name.
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/BlueprintDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/BlueprintDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/BlueprintDAO.java
new file mode 100644
index 0000000..3d5fe78
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/BlueprintDAO.java
@@ -0,0 +1,109 @@
+/**
+ * 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.orm.dao;
+
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.entities.BlueprintEntity;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.List;
+
+
+/**
+ * Blueprint Data Access Object.
+ */
+@Singleton
+public class BlueprintDAO {
+
+ /**
+ * JPA entity manager
+ */
+ @Inject
+ Provider<EntityManager> entityManagerProvider;
+
+ /**
+ * Find a blueprint with a given name.
+ *
+ * @param blueprint_name name of blueprint to find
+ *
+ * @return a matching blueprint or null
+ */
+ public BlueprintEntity findByName(String blueprint_name) {
+ return entityManagerProvider.get().find(BlueprintEntity.class, blueprint_name);
+ }
+
+ /**
+ * Find all blueprints.
+ *
+ * @return all blueprints or an empty List
+ */
+ public List<BlueprintEntity> findAll() {
+ TypedQuery<BlueprintEntity> query = entityManagerProvider.get().
+ createNamedQuery("allBlueprints", BlueprintEntity.class);
+
+ return query.getResultList();
+ }
+
+ /**
+ * Refresh the state of the instance from the database,
+ * overwriting changes made to the entity, if any.
+ *
+ * @param blueprintEntity entity to refresh
+ */
+ @Transactional
+ public void refresh(BlueprintEntity blueprintEntity) {
+ entityManagerProvider.get().refresh(blueprintEntity);
+ }
+
+ /**
+ * Make an instance managed and persistent.
+ *
+ * @param blueprintEntity entity to persist
+ */
+ @Transactional
+ public void create(BlueprintEntity blueprintEntity) {
+ entityManagerProvider.get().persist(blueprintEntity);
+ }
+
+ /**
+ * Merge the state of the given entity into the current persistence context.
+ *
+ * @param blueprintEntity entity to merge
+ * @return the merged entity
+ */
+ @Transactional
+ public BlueprintEntity merge(BlueprintEntity blueprintEntity) {
+ return entityManagerProvider.get().merge(blueprintEntity);
+ }
+
+ /**
+ * Remove the entity instance.
+ *
+ * @param blueprintEntity entity to remove
+ */
+ @Transactional
+ public void remove(BlueprintEntity blueprintEntity) {
+ entityManagerProvider.get().remove(merge(blueprintEntity));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
new file mode 100644
index 0000000..9e89c86
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
@@ -0,0 +1,128 @@
+/**
+ * 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.orm.entities;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.Collection;
+
+/**
+ * Entity representing a Blueprint.
+ */
+@Table(name = "blueprint")
+@NamedQuery(name = "allBlueprints",
+ query = "SELECT blueprint FROM BlueprintEntity blueprint")
+@Entity
+public class BlueprintEntity {
+
+ @Id
+ @Column(name = "blueprint_name", nullable = false, insertable = true,
+ updatable = false, unique = true, length = 100)
+ private String blueprintName;
+
+ @Column(name = "stack_name", nullable = false, insertable = true, updatable = false)
+ @Basic
+ private String stackName;
+
+ @Column(name = "stack_version", nullable = false, insertable = true, updatable = false)
+ @Basic
+ private String stackVersion;
+
+ @OneToMany(cascade = CascadeType.ALL, mappedBy = "blueprint")
+ private Collection<HostGroupEntity> hostGroups;
+
+
+ /**
+ * Get the blueprint name.
+ *
+ * @return blueprint name
+ */
+ public String getBlueprintName() {
+ return blueprintName;
+ }
+
+ /**
+ * Set the blueprint name
+ *
+ * @param blueprintName the blueprint name
+ */
+ public void setBlueprintName(String blueprintName) {
+ this.blueprintName = blueprintName;
+ }
+
+ /**
+ * Get the stack name.
+ *
+ * @return the stack name
+ */
+ public String getStackName() {
+ return stackName;
+ }
+
+ /**
+ * Set the stack name.
+ *
+ * @param stackName the stack name
+ */
+ public void setStackName(String stackName) {
+ this.stackName = stackName;
+ }
+
+ /**
+ * Get the stack version.
+ *
+ * @return the stack version
+ */
+ public String getStackVersion() {
+ return stackVersion;
+ }
+
+ /**
+ * Set the stack version.
+ *
+ * @param stackVersion the stack version
+ */
+ public void setStackVersion(String stackVersion) {
+ this.stackVersion = stackVersion;
+ }
+
+ /**
+ * Get the collection of associated host groups.
+ *
+ * @return collection of host groups
+ */
+ public Collection<HostGroupEntity> getHostGroups() {
+ return hostGroups;
+ }
+
+ /**
+ * Set the host group collection.
+ *
+ * @param hostGroups collection of associated host groups
+ */
+ public void setHostGroups(Collection<HostGroupEntity> hostGroups) {
+ this.hostGroups = hostGroups;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java
new file mode 100644
index 0000000..984c549
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java
@@ -0,0 +1,129 @@
+/**
+ * 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.orm.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+/**
+ * Represents a Host Group Component which is embedded in a Blueprint.
+ */
+@IdClass(HostGroupComponentEntityPK.class)
+@Table(name = "hostgroup_component")
+@Entity
+public class HostGroupComponentEntity {
+
+ @Id
+ @Column(name = "hostgroup_name", nullable = false, insertable = false, updatable = false)
+ private String hostGroupName;
+
+ @Id
+ @Column(name = "blueprint_name", nullable = false, insertable = false, updatable = false)
+ private String blueprintName;
+
+ @Id
+ @Column(name = "name", nullable = false, insertable = true, updatable = false)
+ private String name;
+
+ @ManyToOne
+ @JoinColumns({
+ @JoinColumn(name = "hostgroup_name", referencedColumnName = "name", nullable = false),
+ @JoinColumn(name = "blueprint_name", referencedColumnName = "blueprint_name", nullable = false)
+ })
+ private HostGroupEntity hostGroup;
+
+
+ /**
+ * Get the name of the host group component.
+ *
+ * @return component name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Set the name of the host group component.
+ *
+ * @param name component name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Get the host group entity.
+ *
+ * @return host group entity
+ */
+ public HostGroupEntity getHostGroupEntity() {
+ return hostGroup;
+ }
+
+ /**
+ * Set the host group entity.
+ *
+ * @param entity host group entity
+ */
+ public void setHostGroupEntity(HostGroupEntity entity) {
+ this.hostGroup = entity;
+ }
+
+ /**
+ * Get the name of the associated host group.
+ *
+ * @return host group name
+ */
+ public String getHostGroupName() {
+ return hostGroupName;
+ }
+
+ /**
+ * Set the name of the associated host group.
+ *
+ * @param hostGroupName host group name
+ */
+ public void setHostGroupName(String hostGroupName) {
+ this.hostGroupName = hostGroupName;
+ }
+
+ /**
+ * Get the name of the associated blueprint.
+ *
+ * @return blueprint name
+ */
+ public String getBlueprintName() {
+ return blueprintName;
+ }
+
+ /**
+ * Set the name of the associated blueprint.
+ *
+ * @param blueprintName blueprint name
+ */
+ public void setBlueprintName(String blueprintName) {
+ this.blueprintName = blueprintName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntityPK.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntityPK.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntityPK.java
new file mode 100644
index 0000000..fb9011b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntityPK.java
@@ -0,0 +1,114 @@
+/**
+ * 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.orm.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Id;
+
+/**
+ * Composite primary key for HostGroupComponentEntity.
+ */
+public class HostGroupComponentEntityPK {
+
+ @Id
+ @Column(name = "hostgroup_name", nullable = false, insertable = true, updatable = false, length = 100)
+ private String hostGroupName;
+
+ @Id
+ @Column(name = "blueprint_name", nullable = false, insertable = true, updatable = false, length = 100)
+ private String blueprintName;
+
+ @Id
+ @Column(name = "name", nullable = false, insertable = true, updatable = false, length = 100)
+ private String name;
+
+ /**
+ * Get the name of the associated host group.
+ *
+ * @return host group name
+ */
+ public String getHostGroupName() {
+ return hostGroupName;
+ }
+
+ /**
+ * Set the name of the associated host group.
+ *
+ * @param hostGroupName host group name
+ */
+ public void setHostGroupName(String hostGroupName) {
+ this.hostGroupName = hostGroupName;
+ }
+
+ /**
+ * Get the name of the associated blueprint.
+ *
+ * @return blueprint name
+ */
+ public String getBlueprintName() {
+ return blueprintName;
+ }
+
+ /**
+ * Set the name of the associated blueprint.
+ *
+ * @param blueprintName blueprint name
+ */
+ public void setBlueprintName(String blueprintName) {
+ this.blueprintName = blueprintName;
+ }
+
+ /**
+ * Get the name of the host group component.
+ *
+ * @return component name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Set the name of the host group component.
+ *
+ * @param name component name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ HostGroupComponentEntityPK that = (HostGroupComponentEntityPK) o;
+
+ return this.hostGroupName.equals(that.hostGroupName) &&
+ this.name.equals(that.name) &&
+ this.blueprintName.equals(that.blueprintName);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = hostGroupName.hashCode();
+ result = 31 * result + blueprintName.hashCode();
+ result = 31 * result + name.hashCode();
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntity.java
new file mode 100644
index 0000000..fbc6ef4
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntity.java
@@ -0,0 +1,149 @@
+/**
+ * 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.orm.entities;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.Collection;
+
+/**
+ * Represents a Host Group which is embedded in a Blueprint.
+ */
+@javax.persistence.IdClass(HostGroupEntityPK.class)
+@Table(name = "hostgroup")
+@Entity
+public class HostGroupEntity {
+
+ @Id
+ @Column(name = "blueprint_name", nullable = false, insertable = false, updatable = false)
+ private String blueprintName;
+
+ @Id
+ @Column(name = "name", nullable = false, insertable = true, updatable = false)
+ private String name;
+
+ @Column
+ @Basic
+ private String cardinality;
+
+ @OneToMany(cascade = CascadeType.ALL, mappedBy = "hostGroup")
+ private Collection<HostGroupComponentEntity> components;
+
+ @ManyToOne
+ @JoinColumn(name = "blueprint_name", referencedColumnName = "blueprint_name", nullable = false)
+ private BlueprintEntity blueprint;
+
+
+ /**
+ * Get the host group name.
+ *
+ * @return host group name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Set the host group name.
+ *
+ * @param name host group name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Get the blueprint entity instance.
+ *
+ * @return blueprint entity
+ */
+ public BlueprintEntity getBlueprintEntity() {
+ return blueprint;
+ }
+
+ /**
+ * Set the blueprint entity instance.
+ *
+ * @param entity blueprint entity
+ */
+ public void setBlueprintEntity(BlueprintEntity entity) {
+ this.blueprint = entity;
+ }
+
+ /**
+ * Get the name of the associated blueprint.
+ *
+ * @return blueprint name
+ */
+ public String getBlueprintName() {
+ return blueprintName;
+ }
+
+ /**
+ * Set the name of the associated blueprint.
+ * '
+ * @param blueprintName blueprint name
+ */
+ public void setBlueprintName(String blueprintName) {
+ this.blueprintName = blueprintName;
+ }
+
+ /**
+ * Get the collection of associated component entities.
+ *
+ * @return collection of components
+ */
+ public Collection<HostGroupComponentEntity> getComponents() {
+ return components;
+ }
+
+ /**
+ * Set thge collection of associated component entities.
+ *
+ * @param components collection of components
+ */
+ public void setComponents(Collection<HostGroupComponentEntity> components) {
+ this.components = components;
+ }
+
+ /**
+ * Get the cardinality for this host group.
+ *
+ * @return cardinality
+ */
+ public String getCardinality() {
+ return cardinality;
+ }
+
+ /**
+ * Set the cardinality value for this host group.
+ *
+ * @param cardinality cardinality value
+ */
+ public void setCardinality(String cardinality) {
+ this.cardinality = cardinality;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntityPK.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntityPK.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntityPK.java
new file mode 100644
index 0000000..b5aba5f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntityPK.java
@@ -0,0 +1,88 @@
+/**
+ * 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.orm.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Id;
+
+/**
+ * Composite primary key for HostGroupEntity.
+ */
+public class HostGroupEntityPK {
+
+ @Id
+ @Column(name = "blueprint_name", nullable = false, insertable = true, updatable = false, length = 100)
+ private String blueprintName;
+
+ @Id
+ @Column(name = "name", nullable = false, insertable = true, updatable = false, length = 100)
+ private String name;
+
+ /**
+ * Get the name of the associated blueprint.
+ *
+ * @return blueprint name
+ */
+ public String getBlueprintName() {
+ return blueprintName;
+ }
+
+ /**
+ * Set the name of the associated blueprint.
+ *
+ * @param blueprintName blueprint name
+ */
+ public void setBlueprintName(String blueprintName) {
+ this.blueprintName = blueprintName;
+ }
+
+ /**
+ * Get the name of the host group.
+ *
+ * @return host group name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Set the name of the host group.
+ *
+ * @param name host group name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ HostGroupEntityPK that = (HostGroupEntityPK) o;
+
+ return this.blueprintName.equals(that.blueprintName) &&
+ this.name.equals(that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * blueprintName.hashCode() + name.hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 8b8e285..c9b4bdb 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -55,6 +55,9 @@ CREATE TABLE configgroup (group_id BIGINT, cluster_id BIGINT NOT NULL, group_nam
CREATE TABLE configgrouphostmapping (config_group_id BIGINT NOT NULL, host_name VARCHAR(255) NOT NULL, PRIMARY KEY(config_group_id, host_name));
CREATE TABLE requestschedule (schedule_id bigint, cluster_id BIGINT NOT NULL, description varchar(255), status varchar(255), batch_separation_seconds smallint, batch_toleration_limit smallint, create_user varchar(255), create_timestamp bigint, update_user varchar(255), update_timestamp bigint, minutes varchar(10), hours varchar(10), days_of_month varchar(10), month varchar(10), day_of_week varchar(10), yearToSchedule varchar(10), startTime varchar(50), endTime varchar(50), last_execution_status varchar(255), PRIMARY KEY(schedule_id));
CREATE TABLE requestschedulebatchrequest (schedule_id bigint, batch_id bigint, request_id bigint, request_type varchar(255), request_uri varchar(1024), request_body LONGBLOB, request_status varchar(255), return_code smallint, return_message varchar(2000), PRIMARY KEY(schedule_id, batch_id));
+CREATE TABLE blueprint (blueprint_name VARCHAR(255) NOT NULL, stack_name VARCHAR(255) NOT NULL, stack_version VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name));
+CREATE TABLE hostgroup (blueprint_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, cardinality VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, name));
+CREATE TABLE hostgroup_component (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name));
ALTER TABLE users ADD CONSTRAINT UNQ_users_0 UNIQUE (user_name, ldap_user);
ALTER TABLE clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
@@ -88,6 +91,8 @@ ALTER TABLE configgroup ADD CONSTRAINT FK_configgroup_cluster_id FOREIGN KEY (cl
ALTER TABLE configgrouphostmapping ADD CONSTRAINT FK_configgrouphostmapping_configgroup_id FOREIGN KEY (config_group_id) REFERENCES configgroup (group_id);
ALTER TABLE configgrouphostmapping ADD CONSTRAINT FK_configgrouphostmapping_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
ALTER TABLE requestschedulebatchrequest ADD CONSTRAINT FK_requestschedulebatchrequest_schedule_id FOREIGN KEY (schedule_id) REFERENCES ambari.requestschedule (schedule_id);
+ALTER TABLE hostgroup ADD FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name);
+ALTER TABLE hostgroup_component ADD FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES hostgroup(blueprint_name, name);
INSERT INTO ambari_sequences(sequence_name, value) values ('cluster_id_seq', 1);
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 3f1a080..ed2305b 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -45,6 +45,9 @@ CREATE TABLE confgroupclusterconfigmapping (config_group_id NUMBER(19) NOT NULL,
CREATE TABLE configgrouphostmapping (config_group_id NUMBER(19) NOT NULL, host_name VARCHAR2(255) NOT NULL, PRIMARY KEY(config_group_id, host_name));
CREATE TABLE requestschedule (schedule_id NUMBER(19), cluster_id NUMBER(19) NOT NULL, description VARCHAR2(255), status VARCHAR2(255), batch_separation_seconds smallint, batch_toleration_limit smallint, create_user VARCHAR2(255), create_timestamp NUMBER(19), update_user VARCHAR2(255), update_timestamp NUMBER(19), minutes VARCHAR2(10), hours VARCHAR2(10), days_of_month VARCHAR2(10), month VARCHAR2(10), day_of_week VARCHAR2(10), yearToSchedule VARCHAR2(10), startTime VARCHAR2(50), endTime VARCHAR2(50), last_execution_status VARCHAR2(255), PRIMARY KEY(schedule_id));
CREATE TABLE requestschedulebatchrequest (schedule_id NUMBER(19), batch_id NUMBER(19), request_id NUMBER(19), request_type VARCHAR2(255), request_uri VARCHAR2(1024), request_body BLOB, request_status VARCHAR2(255), return_code smallint, return_message VARCHAR2(2000), PRIMARY KEY(schedule_id, batch_id));
+CREATE TABLE blueprint (blueprint_name VARCHAR2(255) NOT NULL, stack_name VARCHAR2(255) NOT NULL, stack_version VARCHAR2(255) NOT NULL, PRIMARY KEY(blueprint_name));
+CREATE TABLE hostgroup (blueprint_name VARCHAR2(255) NOT NULL, name VARCHAR2(255) NOT NULL, cardinality VARCHAR2(255) NOT NULL, PRIMARY KEY(blueprint_name, name));
+CREATE TABLE hostgroup_component (blueprint_name VARCHAR2(255) NOT NULL, hostgroup_name VARCHAR2(255) NOT NULL, name VARCHAR2(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name));
ALTER TABLE users ADD CONSTRAINT UNQ_users_0 UNIQUE (user_name, ldap_user);
ALTER TABLE clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
@@ -76,6 +79,8 @@ ALTER TABLE confgroupclusterconfigmapping ADD CONSTRAINT FK_cgccm_gid FOREIGN KE
ALTER TABLE configgrouphostmapping ADD CONSTRAINT FK_cghm_cgid FOREIGN KEY (config_group_id) REFERENCES configgroup (group_id);
ALTER TABLE configgrouphostmapping ADD CONSTRAINT FK_cghm_hname FOREIGN KEY (host_name) REFERENCES hosts (host_name);
ALTER TABLE requestschedulebatchrequest ADD CONSTRAINT FK_rsbatchrequest_schedule_id FOREIGN KEY (schedule_id) REFERENCES requestschedule (schedule_id);
+ALTER TABLE hostgroup ADD FOREIGN KEY (blueprint_name) REFERENCES ambari.blueprint(blueprint_name);
+ALTER TABLE hostgroup_component ADD FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES ambari.hostgroup(blueprint_name, name);
INSERT INTO ambari_sequences(sequence_name, value) values ('host_role_command_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, value) values ('user_id_seq', 1);
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 78dce48..6bc6f24 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -116,6 +116,13 @@ GRANT ALL PRIVILEGES ON TABLE ambari.requestschedule TO :username;
CREATE TABLE ambari.requestschedulebatchrequest (schedule_id bigint, batch_id bigint, request_id bigint, request_type varchar(255), request_uri varchar(1024), request_body BYTEA, request_status varchar(255), return_code smallint, return_message varchar(20000), PRIMARY KEY(schedule_id, batch_id));
GRANT ALL PRIVILEGES ON TABLE ambari.requestschedulebatchrequest TO :username;
+CREATE TABLE ambari.blueprint (blueprint_name VARCHAR(255) NOT NULL, stack_name VARCHAR(255) NOT NULL, stack_version VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name));
+CREATE TABLE ambari.hostgroup (blueprint_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, cardinality VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, name));
+CREATE TABLE ambari.hostgroup_component (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name));
+GRANT ALL PRIVILEGES ON TABLE ambari.blueprint TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_component TO :username;
+
--------altering tables by creating foreign keys----------
ALTER TABLE ambari.clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
ALTER TABLE ambari.clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
@@ -148,6 +155,9 @@ ALTER TABLE ambari.confgroupclusterconfigmapping ADD CONSTRAINT FK_confgroupclus
ALTER TABLE ambari.configgrouphostmapping ADD CONSTRAINT FK_configgrouphostmapping_configgroup_id FOREIGN KEY (config_group_id) REFERENCES ambari.configgroup (group_id);
ALTER TABLE ambari.configgrouphostmapping ADD CONSTRAINT FK_configgrouphostmapping_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
ALTER TABLE ambari.requestschedulebatchrequest ADD CONSTRAINT FK_requestschedulebatchrequest_schedule_id FOREIGN KEY (schedule_id) REFERENCES ambari.requestschedule (schedule_id);
+ALTER TABLE ambari.hostgroup ADD FOREIGN KEY (blueprint_name) REFERENCES ambari.blueprint(blueprint_name);
+ALTER TABLE ambari.hostgroup_component ADD FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES ambari.hostgroup(blueprint_name, name);
+
---------inserting some data-----------
BEGIN;
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml
index 3b07bd7..c85d79d 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -41,6 +41,9 @@
<class>org.apache.ambari.server.orm.entities.ActionEntity</class>
<class>org.apache.ambari.server.orm.entities.RequestScheduleEntity</class>
<class>org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntity</class>
+ <class>org.apache.ambari.server.orm.entities.BlueprintEntity</class>
+ <class>org.apache.ambari.server.orm.entities.HostGroupEntity</class>
+ <class>org.apache.ambari.server.orm.entities.HostGroupComponentEntity</class>
<properties>
<!--<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/ambari" />-->
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/resources/key_properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/key_properties.json b/ambari-server/src/main/resources/key_properties.json
index dc7e23a..b3715cb 100644
--- a/ambari-server/src/main/resources/key_properties.json
+++ b/ambari-server/src/main/resources/key_properties.json
@@ -106,5 +106,8 @@
"RequestSchedule" : {
"Cluster": "RequestSchedule/cluster_name",
"RequestSchedule": "RequestSchedule/id"
- }
+ },
+ "Blueprint": {
+ "Blueprint": "Blueprints/blueprint_name"
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/resources/properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json
index 4a824d3..2cd5e35 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -285,16 +285,16 @@
"TaskAttempt/output_bytes",
"TaskAttempt/status",
"TaskAttempt/locality"
- ],
+ ],
"RootService":[
"RootService/service_name"
- ],
+ ],
"RootServiceComponent":[
"RootServiceComponents/service_name",
"RootServiceComponents/component_name",
"RootServiceComponents/properties",
"RootServiceComponents/component_version"
- ],
+ ],
"RootServiceHostComponent":[
"RootServiceHostComponents/service_name",
"RootServiceHostComponents/component_name",
@@ -302,5 +302,13 @@
"RootServiceHostComponents/component_state",
"RootServiceHostComponents/component_version",
"RootServiceHostComponents/properties"
- ]
+ ],
+ "Blueprint":[
+ "Blueprints/blueprint_name",
+ "Blueprints/stack_name",
+ "Blueprints/stack_version",
+ "host_groups",
+ "host_groups/components",
+ "host_groups/cardinality"
+ ]
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-MySQL-UPGRADE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-MySQL-UPGRADE.sql b/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-MySQL-UPGRADE.sql
index 509d1cf..c12aa82 100644
--- a/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-MySQL-UPGRADE.sql
+++ b/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-MySQL-UPGRADE.sql
@@ -83,3 +83,11 @@ create index idx_qrtz_ft_tg on QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
ALTER TABLE hostcomponentdesiredstate ADD passive_state VARCHAR(32) NOT NULL DEFAULT 'ACTIVE';
ALTER TABLE servicedesiredstate ADD passive_state VARCHAR(32) NOT NULL DEFAULT 'ACTIVE';
ALTER TABLE hoststate ADD passive_state VARCHAR(512);
+
+-- blueprint related tables
+CREATE TABLE blueprint (blueprint_name VARCHAR(255) NOT NULL, stack_name VARCHAR(255) NOT NULL, stack_version VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name));
+CREATE TABLE hostgroup (blueprint_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, cardinality VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, name));
+CREATE TABLE hostgroup_component (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name));
+
+ALTER TABLE hostgroup ADD FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name);
+ALTER TABLE hostgroup_component ADD FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES hostgroup(blueprint_name, name);
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-Oracle-UPGRADE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-Oracle-UPGRADE.sql b/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-Oracle-UPGRADE.sql
index a74f2a2..b82f4e8 100644
--- a/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-Oracle-UPGRADE.sql
+++ b/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-Oracle-UPGRADE.sql
@@ -45,7 +45,6 @@ CREATE TABLE configgroup (group_id NUMBER(19), cluster_id NUMBER(19) NOT NULL, g
CREATE TABLE confgroupclusterconfigmapping (config_group_id NUMBER(19) NOT NULL, cluster_id NUMBER(19) NOT NULL, config_type VARCHAR2(255) NOT NULL, version_tag VARCHAR2(255) NOT NULL, user_name VARCHAR2(255) DEFAULT '_db', create_timestamp NUMBER(19) NOT NULL, PRIMARY KEY(config_group_id, cluster_id, config_type));
CREATE TABLE configgrouphostmapping (config_group_id NUMBER(19) NOT NULL, host_name VARCHAR2(255) NOT NULL, PRIMARY KEY(config_group_id, host_name));
-
ALTER TABLE configgroup ADD CONSTRAINT FK_configgroup_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
ALTER TABLE confgroupclusterconfigmapping ADD CONSTRAINT FK_confg FOREIGN KEY (version_tag, config_type, cluster_id) REFERENCES clusterconfig (version_tag, type_name, cluster_id);
ALTER TABLE confgroupclusterconfigmapping ADD CONSTRAINT FK_cgccm_gid FOREIGN KEY (config_group_id) REFERENCES configgroup (group_id);
@@ -55,6 +54,14 @@ ALTER TABLE configgrouphostmapping ADD CONSTRAINT FK_cghm_hname FOREIGN KEY (hos
-- Don't set not null constraint
-- ALTER TABLE stage MODIFY (cluster_host_info NOT NULL);
+-- blueprint related tables
+CREATE TABLE blueprint (blueprint_name VARCHAR2(255) NOT NULL, stack_name VARCHAR2(255) NOT NULL, stack_version VARCHAR2(255) NOT NULL, PRIMARY KEY(blueprint_name));
+CREATE TABLE hostgroup (blueprint_name VARCHAR2(255) NOT NULL, name VARCHAR2(255) NOT NULL, cardinality VARCHAR2(255) NOT NULL, PRIMARY KEY(blueprint_name, name));
+CREATE TABLE hostgroup_component (blueprint_name VARCHAR2(255) NOT NULL, hostgroup_name VARCHAR2(255) NOT NULL, name VARCHAR2(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name));
+
+ALTER TABLE hostgroup ADD FOREIGN KEY (blueprint_name) REFERENCES ambari.blueprint(blueprint_name);
+ALTER TABLE hostgroup_component ADD FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES ambari.hostgroup(blueprint_name, name);
+
-- Abort all tasks in progress due to format change
UPDATE host_role_command SET status = 'ABORTED' WHERE status IN ('PENDING', 'QUEUED', 'IN_PROGRESS');
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-Postgres-UPGRADE-1.3.0.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-Postgres-UPGRADE-1.3.0.sql b/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-Postgres-UPGRADE-1.3.0.sql
index 674d08c..01bf43b 100644
--- a/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-Postgres-UPGRADE-1.3.0.sql
+++ b/ambari-server/src/main/resources/upgrade/ddl/Ambari-DDL-Postgres-UPGRADE-1.3.0.sql
@@ -132,6 +132,18 @@ ALTER TABLE ambari.confgroupclusterconfigmapping ADD CONSTRAINT FK_confgroupclus
ALTER TABLE ambari.configgrouphostmapping ADD CONSTRAINT FK_configgrouphostmapping_configgroup_id FOREIGN KEY (config_group_id) REFERENCES ambari.configgroup (group_id);
ALTER TABLE ambari.configgrouphostmapping ADD CONSTRAINT FK_configgrouphostmapping_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
+-- create blueprint tables
+CREATE TABLE ambari.blueprint (blueprint_name VARCHAR(255) NOT NULL, stack_name VARCHAR(255) NOT NULL, stack_version VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name));
+CREATE TABLE ambari.hostgroup (blueprint_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, cardinality VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, name));
+CREATE TABLE ambari.hostgroup_component (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name));
+GRANT ALL PRIVILEGES ON TABLE ambari.blueprint TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_component TO :username
+-- add fk constraints to blueprint tables
+ALTER TABLE ambari.hostgroup ADD FOREIGN KEY (blueprint_name) REFERENCES ambari.blueprint(blueprint_name);
+ALTER TABLE ambari.hostgroup_component ADD FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES ambari.hostgroup(blueprint_name, name);
+
+
-- add decommission state
ALTER TABLE ambari.hostcomponentdesiredstate ADD COLUMN admin_state VARCHAR(32);
ALTER TABLE ambari.hostcomponentdesiredstate ADD COLUMN passive_state VARCHAR(32) NOT NULL DEFAULT 'ACTIVE'
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BlueprintResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BlueprintResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BlueprintResourceDefinitionTest.java
new file mode 100644
index 0000000..a4531c3
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BlueprintResourceDefinitionTest.java
@@ -0,0 +1,53 @@
+/**
+ * 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.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * BlueprintResourceDefinition tests.
+ */
+public class BlueprintResourceDefinitionTest {
+
+ @Test
+ public void testGetType() throws Exception {
+ BlueprintResourceDefinition definition = new BlueprintResourceDefinition();
+ Assert.assertEquals(Resource.Type.Blueprint, definition.getType());
+ }
+
+ @Test
+ public void testGetPluralName() throws Exception {
+ BlueprintResourceDefinition definition = new BlueprintResourceDefinition();
+ Assert.assertEquals("blueprints", definition.getPluralName());
+ }
+
+ @Test
+ public void testGetSingularName() throws Exception {
+ BlueprintResourceDefinition definition = new BlueprintResourceDefinition();
+ Assert.assertEquals("blueprint", definition.getSingularName());
+ }
+
+ @Test
+ public void testGetSubResourceDefinitions() {
+ BlueprintResourceDefinition definition = new BlueprintResourceDefinition();
+ Assert.assertTrue(definition.getSubResourceDefinitions().isEmpty());
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5f464316/ambari-server/src/test/java/org/apache/ambari/server/api/services/BlueprintServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/BlueprintServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/BlueprintServiceTest.java
new file mode 100644
index 0000000..b109e96
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/BlueprintServiceTest.java
@@ -0,0 +1,104 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.parsers.RequestBodyParser;
+import org.apache.ambari.server.api.services.serializers.ResultSerializer;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit tests for BlueprintService.
+ */
+public class BlueprintServiceTest extends BaseServiceTest {
+
+
+ public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+ List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+ //getBlueprint
+ BlueprintService BlueprintService = new TestBlueprintService("blueprintName");
+ Method m = BlueprintService.getClass().getMethod("getBlueprint", HttpHeaders.class, UriInfo.class, String.class);
+ Object[] args = new Object[] {getHttpHeaders(), getUriInfo(), "blueprintName"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, BlueprintService, m, args, null));
+
+ //getBlueprints
+ BlueprintService = new TestBlueprintService(null);
+ m = BlueprintService.getClass().getMethod("getBlueprints", HttpHeaders.class, UriInfo.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo()};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, BlueprintService, m, args, null));
+
+ //createBlueprint
+ BlueprintService = new TestBlueprintService("blueprintName");
+ m = BlueprintService.getClass().getMethod("createBlueprint", String.class, HttpHeaders.class, UriInfo.class, String.class);
+ args = new Object[] {"body", getHttpHeaders(), getUriInfo(), "blueprintName"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.POST, BlueprintService, m, args, "body"));
+
+ //deleteBlueprint
+ BlueprintService = new TestBlueprintService("blueprintName");
+ m = BlueprintService.getClass().getMethod("deleteBlueprint", HttpHeaders.class, UriInfo.class, String.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo(), "blueprintName"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.DELETE, BlueprintService, m, args, null));
+
+ //deleteBlueprints
+ BlueprintService = new TestBlueprintService(null);
+ m = BlueprintService.getClass().getMethod("deleteBlueprints", HttpHeaders.class, UriInfo.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo()};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.DELETE, BlueprintService, m, args, null));
+
+ return listInvocations;
+ }
+
+
+ private class TestBlueprintService extends BlueprintService {
+ private String m_blueprintId;
+
+ private TestBlueprintService(String blueprintId) {
+ m_blueprintId = blueprintId;
+ }
+
+ @Override
+ ResourceInstance createBlueprintResource(String blueprintName) {
+ assertEquals(m_blueprintId, blueprintName);
+ return getTestResource();
+ }
+
+ @Override
+ RequestFactory getRequestFactory() {
+ return getTestRequestFactory();
+ }
+
+ @Override
+ protected RequestBodyParser getBodyParser() {
+ return getTestBodyParser();
+ }
+
+ @Override
+ protected ResultSerializer getResultSerializer() {
+ return getTestResultSerializer();
+ }
+ }
+}
\ No newline at end of file