Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 28E43162D36 for ; Tue, 22 Aug 2017 14:03:52 +0200 (CEST) Received: (qmail 86219 invoked by uid 500); 22 Aug 2017 12:03:51 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 85774 invoked by uid 99); 22 Aug 2017 12:03:50 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 22 Aug 2017 12:03:50 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 4878BF32C8; Tue, 22 Aug 2017 12:03:48 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: lpuskas@apache.org To: commits@ambari.apache.org Date: Tue, 22 Aug 2017 12:03:53 -0000 Message-Id: In-Reply-To: <3c21feb3f47f4ffc8aed4813985dc154@git.apache.org> References: <3c21feb3f47f4ffc8aed4813985dc154@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [06/10] ambari git commit: AMBARI-21307 Rest resource for supporting ambari configurations AMBARI-21307 Rest resource for supporting ambari configurations Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/159d6179 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/159d6179 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/159d6179 Branch: refs/heads/feature-branch-AMBARI-21307 Commit: 159d6179834f81c33fe0d7a39d78c145fb74939c Parents: 6f9f87c Author: lpuskas Authored: Wed Jul 5 14:20:18 2017 +0200 Committer: lpuskas Committed: Tue Aug 22 14:03:24 2017 +0200 ---------------------------------------------------------------------- .../resources/ResourceInstanceFactoryImpl.java | 4 + .../services/AmbariConfigurationService.java | 146 +++++++++++ .../internal/AbstractProviderModule.java | 2 +- .../AmbariConfigurationResourceProvider.java | 247 +++++++++++++++++++ .../internal/DefaultProviderModule.java | 26 +- .../ambari/server/controller/spi/Resource.java | 5 +- .../server/orm/dao/AmbariConfigurationDAO.java | 92 +++++++ .../orm/entities/AmbariConfigurationEntity.java | 70 ++++++ .../orm/entities/ConfigurationBaseEntity.java | 159 ++++++++++++ .../authorization/RoleAuthorization.java | 95 +++---- .../resources/Ambari-DDL-Postgres-CREATE.sql | 25 +- .../src/main/resources/META-INF/persistence.xml | 2 + 12 files changed, 809 insertions(+), 64 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/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 d0d115d..f5fb6e9 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 @@ -471,6 +471,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory { case RemoteCluster: resourceDefinition = new RemoteClusterResourceDefinition(); break; + case AmbariConfiguration: + resourceDefinition = new SimpleResourceDefinition(Resource.Type.AmbariConfiguration, "ambariconfiguration", "ambariconfigurations"); + + break; default: throw new IllegalArgumentException("Unsupported resource type: " + type); http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java new file mode 100644 index 0000000..0fa6e44 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java @@ -0,0 +1,146 @@ +/* + * Licensed 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 java.util.Collections; + +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +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.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.http.HttpStatus; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +/** + * Rest endpoint for managing ambari configurations. Supports CRUD operations. + * Ambari configurations are resources that relate to the ambari server instance even before a cluster is provisioned. + * + * Ambari configuration resources may be shared with components and services in the cluster + * (by recommending them as default values) + * + * Eg. LDAP configuration is stored as ambariconfiguration. + * The request payload has the form: + * + *
+ *      {
+ *        "AmbariConfiguration": {
+ *            "type": "ldap-configuration",
+ *            "data": [
+ *                {
+ *                 "authentication.ldap.primaryUrl": "localhost:33389"
+ *                },
+ *                {
+ *                "authentication.ldap.secondaryUrl": "localhost:333"
+ *                 },
+ *                 {
+ *                 "authentication.ldap.baseDn": "dc=ambari,dc=apache,dc=org"
+ *                 }
+ *                 // ......
+ *             ]
+ *         }
+ *     }
+ * 
+ */ +@Path("/configurations/") +@Api(value = "/configurations", description = "Endpoint for Ambari configuration related operations") +public class AmbariConfigurationService extends BaseService { + + /** + * Creates an ambari configuration resource. + * + * @param body the payload in json format + * @param headers http headers + * @param uri request uri information + * @return + */ + @POST + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Creates an ambari configuration resource") + @ApiImplicitParams({ + @ApiImplicitParam(dataType = "", paramType = PARAM_TYPE_BODY) + }) + @ApiResponses({ + @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS), + @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS), + @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), + @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), + }) + public Response createAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri) { + return handleRequest(headers, body, uri, Request.Type.POST, createResource(Resource.Type.AmbariConfiguration, + Collections.EMPTY_MAP)); + } + + @GET + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Retrieve ambari configuration resources") + public Response getAmbariConfigurations(String body, @Context HttpHeaders headers, @Context UriInfo uri) { + return handleRequest(headers, body, uri, Request.Type.GET, createResource(Resource.Type.AmbariConfiguration, + Collections.EMPTY_MAP)); + } + + @GET + @Path("{configurationId}") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Retrieve ambari configuration resource") + public Response getAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri, + @PathParam("configurationId") String configurationId) { + return handleRequest(headers, body, uri, Request.Type.GET, createResource(Resource.Type.AmbariConfiguration, + Collections.singletonMap(Resource.Type.AmbariConfiguration, configurationId))); + } + + @PUT + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Update ambari configuration resources") + public Response updateAmbariConfiguration() { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @DELETE + @Path("{configurationId}") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Deletes an ambari configuration resource") + @ApiResponses({ + @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), + @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), + @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), + }) + public Response deleteAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri, + @PathParam("configurationId") String configurationId) { + return handleRequest(headers, body, uri, Request.Type.DELETE, createResource(Resource.Type.AmbariConfiguration, + Collections.singletonMap(Resource.Type.AmbariConfiguration, configurationId))); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java index 77549f5..7ad9f41 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java @@ -221,7 +221,7 @@ public abstract class AbstractProviderModule implements ProviderModule, private final Map> propertyProviders = new HashMap<>(); @Inject - AmbariManagementController managementController; + protected AmbariManagementController managementController; @Inject TimelineMetricCacheProvider metricCacheProvider; http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java new file mode 100644 index 0000000..5e5af9e --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java @@ -0,0 +1,247 @@ +/* + * Licensed 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 java.util.Calendar; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.StaticallyInject; +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.PredicateHelper; +import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO; +import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity; +import org.apache.ambari.server.orm.entities.ConfigurationBaseEntity; +import org.apache.ambari.server.security.authorization.RoleAuthorization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Sets; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +/** + * Resource provider for AmbariConfiguration resources. + */ +@StaticallyInject +public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResourceProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(AmbariConfigurationResourceProvider.class); + private static final String DEFAULT_VERSION_TAG = "Default version"; + private static final Integer DEFAULT_VERSION = 1; + + /** + * Resource property id constants. + */ + private enum ResourcePropertyId { + + ID("AmbariConfiguration/id"), + TYPE("AmbariConfiguration/type"), + VERSION("AmbariConfiguration/version"), + VERSION_TAG("AmbariConfiguration/version_tag"), + DATA("AmbariConfiguration/data"); + + private String propertyId; + + ResourcePropertyId(String propertyId) { + this.propertyId = propertyId; + } + + String getPropertyId() { + return this.propertyId; + } + + public static ResourcePropertyId fromString(String propertyIdStr) { + ResourcePropertyId propertyIdFromStr = null; + + for (ResourcePropertyId id : ResourcePropertyId.values()) { + if (id.getPropertyId().equals(propertyIdStr)) { + propertyIdFromStr = id; + break; + } + } + + if (propertyIdFromStr == null) { + throw new IllegalArgumentException("Unsupported property type: " + propertyIdStr); + } + + return propertyIdFromStr; + + } + } + + private static Set properties = Sets.newHashSet( + ResourcePropertyId.ID.getPropertyId(), + ResourcePropertyId.TYPE.getPropertyId(), + ResourcePropertyId.VERSION.getPropertyId(), + ResourcePropertyId.VERSION_TAG.getPropertyId(), + ResourcePropertyId.DATA.getPropertyId()); + + private static Map pkPropertyMap = Collections.unmodifiableMap( + new HashMap() {{ + put(Resource.Type.AmbariConfiguration, ResourcePropertyId.ID.getPropertyId()); + }} + ); + + + @Inject + private static AmbariConfigurationDAO ambariConfigurationDAO; + + private Gson gson; + + protected AmbariConfigurationResourceProvider() { + super(properties, pkPropertyMap); + setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION)); + setRequiredDeleteAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION)); + + gson = new GsonBuilder().create(); + } + + @Override + protected Set getPKPropertyIds() { + return Sets.newHashSet("AmbariConfiguration/id"); + } + + @Override + public RequestStatus createResourcesAuthorized(Request request) throws SystemException, UnsupportedPropertyException, + ResourceAlreadyExistsException, NoSuchParentResourceException { + + LOGGER.info("Creating new ambari configuration resource ..."); + AmbariConfigurationEntity ambariConfigurationEntity = getEntityFromRequest(request); + + LOGGER.info("Persisting new ambari configuration: {} ", ambariConfigurationEntity); + ambariConfigurationDAO.persist(ambariConfigurationEntity); + + return getRequestStatus(null); + } + + + @Override + protected Set getResourcesAuthorized(Request request, Predicate predicate) throws SystemException, + UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { + Set resources = Sets.newHashSet(); + + List ambariConfigurationEntities = ambariConfigurationDAO.findAll(); + for (AmbariConfigurationEntity ambariConfigurationEntity : ambariConfigurationEntities) { + try { + resources.add(toResource(ambariConfigurationEntity, getPropertyIds())); + } catch (AmbariException e) { + LOGGER.error("Error while retrieving ambari configuration", e); + } + } + return resources; + } + + @Override + protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate) throws SystemException, + UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { + + Long idFromRequest = Long.valueOf((String) PredicateHelper.getProperties(predicate).get(ResourcePropertyId.ID.getPropertyId())); + + if (null == idFromRequest) { + LOGGER.debug("No resource id provided in the request"); + } else { + LOGGER.debug("Deleting amari configuration with id: {}", idFromRequest); + try { + ambariConfigurationDAO.deleteById(idFromRequest); + } catch (IllegalStateException e) { + throw new NoSuchResourceException(e.getMessage()); + } + + } + + return getRequestStatus(null); + + } + + private Resource toResource(AmbariConfigurationEntity entity, Set requestedIds) throws AmbariException { + Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration); + Set> configurationSet = gson.fromJson(entity.getConfigurationBaseEntity().getConfigurationData(), Set.class); + + setResourceProperty(resource, ResourcePropertyId.ID.getPropertyId(), entity.getId(), requestedIds); + setResourceProperty(resource, ResourcePropertyId.TYPE.getPropertyId(), entity.getConfigurationBaseEntity().getType(), requestedIds); + setResourceProperty(resource, ResourcePropertyId.DATA.getPropertyId(), configurationSet, requestedIds); + + return resource; + } + + private AmbariConfigurationEntity getEntityFromRequest(Request request) { + + AmbariConfigurationEntity ambariConfigurationEntity = new AmbariConfigurationEntity(); + ambariConfigurationEntity.setConfigurationBaseEntity(new ConfigurationBaseEntity()); + + + for (ResourcePropertyId resourcePropertyId : ResourcePropertyId.values()) { + Object requestValue = getValueFromRequest(resourcePropertyId, request); + + switch (resourcePropertyId) { + case DATA: + if (requestValue == null) { + throw new IllegalArgumentException("No configuration data is provided in the request"); + } + + ambariConfigurationEntity.getConfigurationBaseEntity().setConfigurationData(gson.toJson(requestValue)); + break; + case TYPE: + ambariConfigurationEntity.getConfigurationBaseEntity().setType((String) requestValue); + break; + + case VERSION: + Integer version = (requestValue == null) ? DEFAULT_VERSION : Integer.valueOf((Integer) requestValue); + ambariConfigurationEntity.getConfigurationBaseEntity().setVersion((version)); + break; + case VERSION_TAG: + String versionTag = requestValue == null ? DEFAULT_VERSION_TAG : (String) requestValue; + ambariConfigurationEntity.getConfigurationBaseEntity().setVersionTag(versionTag); + break; + default: + LOGGER.debug("Ignored property in the request: {}", resourcePropertyId); + break; + } + } + ambariConfigurationEntity.getConfigurationBaseEntity().setCreateTimestamp(Calendar.getInstance().getTimeInMillis()); + return ambariConfigurationEntity; + + } + + private Object getValueFromRequest(ResourcePropertyId resourcePropertyIdEnum, Request request) { + LOGGER.debug("Locating resource property [{}] in the request ...", resourcePropertyIdEnum); + Object requestValue = null; + for (Map propertyMap : request.getProperties()) { + if (propertyMap.containsKey(resourcePropertyIdEnum.getPropertyId())) { + requestValue = propertyMap.get(resourcePropertyIdEnum.getPropertyId()); + LOGGER.debug("Found resource property {} in the request, value: {} ...", resourcePropertyIdEnum, requestValue); + break; + } + } + return requestValue; + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/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 074f8e1..6e7ca0a 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 @@ -21,20 +21,18 @@ package org.apache.ambari.server.controller.internal; import java.util.Map; import java.util.Set; -import org.apache.ambari.server.controller.AmbariManagementController; -import org.apache.ambari.server.controller.AmbariServer; 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 com.google.inject.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The default provider module implementation. */ public class DefaultProviderModule extends AbstractProviderModule { - @Inject - private AmbariManagementController managementController; + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultProviderModule.class); // ----- Constructors ------------------------------------------------------ @@ -42,9 +40,7 @@ public class DefaultProviderModule extends AbstractProviderModule { * Create a default provider module. */ public DefaultProviderModule() { - if (managementController == null) { - managementController = AmbariServer.getController(); - } + super(); } @@ -52,8 +48,10 @@ public class DefaultProviderModule extends AbstractProviderModule { @Override protected ResourceProvider createResourceProvider(Resource.Type type) { - Set propertyIds = PropertyHelper.getPropertyIds(type); - Map keyPropertyIds = PropertyHelper.getKeyPropertyIds(type); + + LOGGER.debug("Creating resource provider for the type: {}", type); + Set propertyIds = PropertyHelper.getPropertyIds(type); + Map keyPropertyIds = PropertyHelper.getKeyPropertyIds(type); switch (type.getInternalType()) { case Workflow: @@ -124,10 +122,12 @@ public class DefaultProviderModule extends AbstractProviderModule { return new ArtifactResourceProvider(managementController); case RemoteCluster: return new RemoteClusterResourceProvider(); - + case AmbariConfiguration: + return new AmbariConfigurationResourceProvider(); default: + LOGGER.debug("Delegating creation of resource provider for: {} to the AbstractControllerResourceProvider", type.getInternalType()); return AbstractControllerResourceProvider.getResourceProvider(type, propertyIds, - keyPropertyIds, managementController); + keyPropertyIds, managementController); } } } http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/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 362b4e6..7835373 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 @@ -160,7 +160,8 @@ public interface Resource { VersionDefinition, ClusterKerberosDescriptor, LoggingQuery, - RemoteCluster; + RemoteCluster, + AmbariConfiguration; /** * Get the {@link Type} that corresponds to this InternalType. @@ -282,6 +283,8 @@ public interface Resource { public static final Type ClusterKerberosDescriptor = InternalType.ClusterKerberosDescriptor.getType(); public static final Type LoggingQuery = InternalType.LoggingQuery.getType(); public static final Type RemoteCluster = InternalType.RemoteCluster.getType(); + public static final Type AmbariConfiguration = InternalType.AmbariConfiguration.getType(); + /** * The type name. http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AmbariConfigurationDAO.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AmbariConfigurationDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AmbariConfigurationDAO.java new file mode 100644 index 0000000..dea37eb --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AmbariConfigurationDAO.java @@ -0,0 +1,92 @@ +/* + * Licensed 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 java.util.List; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; + +import org.apache.ambari.server.orm.RequiresSession; +import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.inject.persist.Transactional; + +/** + * DAO dealing with ambari configuration related JPA operations. + */ + +@Singleton +// todo extend CrudDao (amend crud dao to handle NPEs) +public class AmbariConfigurationDAO { + + private static final Logger LOGGER = LoggerFactory.getLogger(AmbariConfigurationDAO.class); + + @Inject + private Provider entityManagerProvider; + + /** + * DAO utilities for dealing mostly with {@link TypedQuery} results. + */ + @Inject + private DaoUtils daoUtils; + + public AmbariConfigurationEntity findByid(Long id) { + return entityManagerProvider.get().find(AmbariConfigurationEntity.class, id); + } + + @RequiresSession + @Transactional + public void persist(AmbariConfigurationEntity entity) { + LOGGER.debug("Persisting ambari configuration: {}", entity); + entityManagerProvider.get().persist(entity); + } + + @RequiresSession + public List findAll() { + TypedQuery query = entityManagerProvider.get().createNamedQuery( + "AmbariConfigurationEntity.findAll", AmbariConfigurationEntity.class); + return daoUtils.selectList(query); + } + + + @RequiresSession + @Transactional + public void deleteById(Long ambariConfigurationId) { + + if (ambariConfigurationId == null) { + throw new IllegalArgumentException("No Ambari Configuration id provided."); + } + + LOGGER.debug("Removing Ambari Configuration with id :{}", ambariConfigurationId); + + AmbariConfigurationEntity ambariConfigurationEntity = findByid(ambariConfigurationId); + if (ambariConfigurationEntity == null) { + String msg = String.format("No Ambari Configuration found with id: %s", ambariConfigurationId); + LOGGER.debug(msg); + throw new IllegalStateException(msg); + } + + entityManagerProvider.get().remove(ambariConfigurationEntity); + LOGGER.debug("Ambari Configuration with id: {}", ambariConfigurationId); + } + + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AmbariConfigurationEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AmbariConfigurationEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AmbariConfigurationEntity.java new file mode 100644 index 0000000..34fa221 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AmbariConfigurationEntity.java @@ -0,0 +1,70 @@ +/* + * Licensed 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.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.MapsId; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToOne; +import javax.persistence.Table; + +@Entity +@Table(name = "ambari_configuration") +@NamedQueries({ + @NamedQuery( + name = "AmbariConfigurationEntity.findAll", + query = "select ace from AmbariConfigurationEntity ace") +}) + +public class AmbariConfigurationEntity { + + @Id + @Column(name = "id") + private Long id; + + @OneToOne(cascade = CascadeType.ALL) + @MapsId + @JoinColumn(name = "id") + private ConfigurationBaseEntity configurationBaseEntity; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public ConfigurationBaseEntity getConfigurationBaseEntity() { + return configurationBaseEntity; + } + + public void setConfigurationBaseEntity(ConfigurationBaseEntity configurationBaseEntity) { + this.configurationBaseEntity = configurationBaseEntity; + } + + @Override + public String toString() { + return "AmbariConfigurationEntity{" + + "id=" + id + + ", configurationBaseEntity=" + configurationBaseEntity + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ConfigurationBaseEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ConfigurationBaseEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ConfigurationBaseEntity.java new file mode 100644 index 0000000..9ad30d7 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ConfigurationBaseEntity.java @@ -0,0 +1,159 @@ +/* + * Licensed 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.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.TableGenerator; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +@Table(name = "configuration_base") +@TableGenerator( + name = "configuration_id_generator", + table = "ambari_sequences", + pkColumnName = "sequence_name", + valueColumnName = "sequence_value", + pkColumnValue = "configuration_id_seq", + initialValue = 1 +) +@Entity +public class ConfigurationBaseEntity { + + @Id + @Column(name = "id") + @GeneratedValue(strategy = GenerationType.TABLE, generator = "configuration_id_generator") + private Long id; + + @Column(name = "version") + private Integer version; + + @Column(name = "version_tag") + private String versionTag; + + @Column(name = "type") + private String type; + + @Column(name = "data") + private String configurationData; + + @Column(name = "attributes") + private String configurationAttributes; + + @Column(name = "create_timestamp") + private Long createTimestamp; + + public Long getId() { + return id; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + public String getVersionTag() { + return versionTag; + } + + public void setVersionTag(String versionTag) { + this.versionTag = versionTag; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getConfigurationData() { + return configurationData; + } + + public void setConfigurationData(String configurationData) { + this.configurationData = configurationData; + } + + public String getConfigurationAttributes() { + return configurationAttributes; + } + + public void setConfigurationAttributes(String configurationAttributes) { + this.configurationAttributes = configurationAttributes; + } + + public Long getCreateTimestamp() { + return createTimestamp; + } + + public void setCreateTimestamp(Long createTimestamp) { + this.createTimestamp = createTimestamp; + } + + @Override + public String toString() { + return "ConfigurationBaseEntity{" + + "id=" + id + + ", version=" + version + + ", versionTag='" + versionTag + '\'' + + ", type='" + type + '\'' + + ", configurationData='" + configurationData + '\'' + + ", configurationAttributes='" + configurationAttributes + '\'' + + ", createTimestamp=" + createTimestamp + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + ConfigurationBaseEntity that = (ConfigurationBaseEntity) o; + + return new EqualsBuilder() + .append(id, that.id) + .append(version, that.version) + .append(versionTag, that.versionTag) + .append(type, that.type) + .append(configurationData, that.configurationData) + .append(configurationAttributes, that.configurationAttributes) + .append(createTimestamp, that.createTimestamp) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(id) + .append(version) + .append(versionTag) + .append(type) + .append(configurationData) + .append(configurationAttributes) + .append(createTimestamp) + .toHashCode(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java index cd35c2c..3c50628 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java @@ -39,6 +39,7 @@ public enum RoleAuthorization { AMBARI_MANAGE_VIEWS("AMBARI.MANAGE_VIEWS"), AMBARI_RENAME_CLUSTER("AMBARI.RENAME_CLUSTER"), AMBARI_RUN_CUSTOM_COMMAND("AMBARI.RUN_CUSTOM_COMMAND"), + AMBARI_MANAGE_CONFIGURATION("AMBARI.MANAGE_CONFIGURATION"), CLUSTER_MANAGE_CREDENTIALS("CLUSTER.MANAGE_CREDENTIALS"), CLUSTER_MODIFY_CONFIGS("CLUSTER.MODIFY_CONFIGS"), CLUSTER_MANAGE_CONFIG_GROUPS("CLUSTER.MANAGE_CONFIG_GROUPS"), @@ -84,58 +85,58 @@ public enum RoleAuthorization { VIEW_USE("VIEW.USE"); public static final Set AUTHORIZATIONS_VIEW_CLUSTER = EnumSet.of( - CLUSTER_VIEW_STATUS_INFO, - CLUSTER_VIEW_ALERTS, - CLUSTER_VIEW_CONFIGS, - CLUSTER_VIEW_METRICS, - CLUSTER_VIEW_STACK_DETAILS, - CLUSTER_MODIFY_CONFIGS, - CLUSTER_MANAGE_CONFIG_GROUPS, - CLUSTER_TOGGLE_ALERTS, - CLUSTER_TOGGLE_KERBEROS, - CLUSTER_UPGRADE_DOWNGRADE_STACK); + CLUSTER_VIEW_STATUS_INFO, + CLUSTER_VIEW_ALERTS, + CLUSTER_VIEW_CONFIGS, + CLUSTER_VIEW_METRICS, + CLUSTER_VIEW_STACK_DETAILS, + CLUSTER_MODIFY_CONFIGS, + CLUSTER_MANAGE_CONFIG_GROUPS, + CLUSTER_TOGGLE_ALERTS, + CLUSTER_TOGGLE_KERBEROS, + CLUSTER_UPGRADE_DOWNGRADE_STACK); public static final Set AUTHORIZATIONS_UPDATE_CLUSTER = EnumSet.of( - CLUSTER_TOGGLE_ALERTS, - CLUSTER_TOGGLE_KERBEROS, - CLUSTER_UPGRADE_DOWNGRADE_STACK, - CLUSTER_MODIFY_CONFIGS, - CLUSTER_MANAGE_AUTO_START, - SERVICE_MODIFY_CONFIGS); + CLUSTER_TOGGLE_ALERTS, + CLUSTER_TOGGLE_KERBEROS, + CLUSTER_UPGRADE_DOWNGRADE_STACK, + CLUSTER_MODIFY_CONFIGS, + CLUSTER_MANAGE_AUTO_START, + SERVICE_MODIFY_CONFIGS); public static final Set AUTHORIZATIONS_VIEW_SERVICE = EnumSet.of( - SERVICE_VIEW_ALERTS, - SERVICE_VIEW_CONFIGS, - SERVICE_VIEW_METRICS, - SERVICE_VIEW_STATUS_INFO, - SERVICE_COMPARE_CONFIGS, - SERVICE_ADD_DELETE_SERVICES, - SERVICE_DECOMMISSION_RECOMMISSION, - SERVICE_ENABLE_HA, - SERVICE_MANAGE_CONFIG_GROUPS, - SERVICE_MODIFY_CONFIGS, - SERVICE_START_STOP, - SERVICE_TOGGLE_MAINTENANCE, - SERVICE_TOGGLE_ALERTS, - SERVICE_MOVE, - SERVICE_RUN_CUSTOM_COMMAND, - SERVICE_RUN_SERVICE_CHECK); + SERVICE_VIEW_ALERTS, + SERVICE_VIEW_CONFIGS, + SERVICE_VIEW_METRICS, + SERVICE_VIEW_STATUS_INFO, + SERVICE_COMPARE_CONFIGS, + SERVICE_ADD_DELETE_SERVICES, + SERVICE_DECOMMISSION_RECOMMISSION, + SERVICE_ENABLE_HA, + SERVICE_MANAGE_CONFIG_GROUPS, + SERVICE_MODIFY_CONFIGS, + SERVICE_START_STOP, + SERVICE_TOGGLE_MAINTENANCE, + SERVICE_TOGGLE_ALERTS, + SERVICE_MOVE, + SERVICE_RUN_CUSTOM_COMMAND, + SERVICE_RUN_SERVICE_CHECK); public static final Set AUTHORIZATIONS_UPDATE_SERVICE = EnumSet.of( - SERVICE_ADD_DELETE_SERVICES, - SERVICE_DECOMMISSION_RECOMMISSION, - SERVICE_ENABLE_HA, - SERVICE_MANAGE_CONFIG_GROUPS, - SERVICE_MODIFY_CONFIGS, - SERVICE_START_STOP, - SERVICE_TOGGLE_MAINTENANCE, - SERVICE_TOGGLE_ALERTS, - SERVICE_MOVE, - SERVICE_RUN_CUSTOM_COMMAND, - SERVICE_RUN_SERVICE_CHECK, - SERVICE_MANAGE_ALERTS, - SERVICE_MANAGE_AUTO_START, - SERVICE_SET_SERVICE_USERS_GROUPS); + SERVICE_ADD_DELETE_SERVICES, + SERVICE_DECOMMISSION_RECOMMISSION, + SERVICE_ENABLE_HA, + SERVICE_MANAGE_CONFIG_GROUPS, + SERVICE_MODIFY_CONFIGS, + SERVICE_START_STOP, + SERVICE_TOGGLE_MAINTENANCE, + SERVICE_TOGGLE_ALERTS, + SERVICE_MOVE, + SERVICE_RUN_CUSTOM_COMMAND, + SERVICE_RUN_SERVICE_CHECK, + SERVICE_MANAGE_ALERTS, + SERVICE_MANAGE_AUTO_START, + SERVICE_SET_SERVICE_USERS_GROUPS); private final String id; @@ -162,7 +163,7 @@ public enum RoleAuthorization { /** * Safely translates a role authorization Id to a RoleAuthorization * - * @param authenticationId an authentication id + * @param authenticationId an authentication id * @return a RoleAuthorization or null if no translation can be made */ public static RoleAuthorization translate(String authenticationId) { http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/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 a6f5cb7..5320a251 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -62,8 +62,26 @@ CREATE TABLE clusters ( desired_cluster_state VARCHAR(255) NOT NULL, desired_stack_id BIGINT NOT NULL, CONSTRAINT PK_clusters PRIMARY KEY (cluster_id), - CONSTRAINT FK_clusters_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), - CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id)); + CONSTRAINT FK_clusters_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack (stack_id), + CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource (resource_id) +); + +CREATE TABLE configuration_base ( + id BIGINT NOT NULL, + version_tag VARCHAR(255) NOT NULL, + version BIGINT NOT NULL, + type VARCHAR(255) NOT NULL, + data TEXT NOT NULL, + attributes TEXT, + create_timestamp BIGINT NOT NULL, + CONSTRAINT PK_configuration_base PRIMARY KEY (id) +); + +CREATE TABLE ambari_configuration ( + id BIGINT NOT NULL, + CONSTRAINT PK_ambari_configuration PRIMARY KEY (id), + CONSTRAINT FK_ambari_configuration_configuration_base FOREIGN KEY (id) REFERENCES configuration_base (id) +); CREATE TABLE clusterconfig ( config_id BIGINT NOT NULL, @@ -1087,6 +1105,7 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) VALUES ('remote_cluster_id_seq', 0), ('remote_cluster_service_id_seq', 0), ('servicecomponent_version_id_seq', 0), + ('configuration_id_seq', 0), ('hostcomponentdesiredstate_id_seq', 0); INSERT INTO adminresourcetype (resource_type_id, resource_type_name) VALUES @@ -1171,6 +1190,7 @@ INSERT INTO roleauthorization(authorization_id, authorization_name) SELECT 'AMBARI.ADD_DELETE_CLUSTERS', 'Create new clusters' UNION ALL SELECT 'AMBARI.RENAME_CLUSTER', 'Rename clusters' UNION ALL SELECT 'AMBARI.MANAGE_SETTINGS', 'Manage administrative settings' UNION ALL + SELECT 'AMBARI.MANAGE_CONFIGURATION', 'Manage ambari configuration' UNION ALL SELECT 'AMBARI.MANAGE_USERS', 'Manage users' UNION ALL SELECT 'AMBARI.MANAGE_GROUPS', 'Manage groups' UNION ALL SELECT 'AMBARI.MANAGE_VIEWS', 'Manage Ambari Views' UNION ALL @@ -1376,6 +1396,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id) SELECT permission_id, 'AMBARI.ADD_DELETE_CLUSTERS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL SELECT permission_id, 'AMBARI.RENAME_CLUSTER' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL SELECT permission_id, 'AMBARI.MANAGE_SETTINGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL + SELECT permission_id, 'AMBARI.MANAGE_CONFIGURATION' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL SELECT permission_id, 'AMBARI.MANAGE_USERS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL SELECT permission_id, 'AMBARI.MANAGE_GROUPS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL SELECT permission_id, 'AMBARI.MANAGE_VIEWS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL http://git-wip-us.apache.org/repos/asf/ambari/blob/159d6179/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 e4045ef..0f8e964 100644 --- a/ambari-server/src/main/resources/META-INF/persistence.xml +++ b/ambari-server/src/main/resources/META-INF/persistence.xml @@ -96,6 +96,8 @@ org.apache.ambari.server.orm.entities.KerberosDescriptorEntity org.apache.ambari.server.orm.entities.RemoteAmbariClusterEntity org.apache.ambari.server.orm.entities.RemoteAmbariClusterServiceEntity + org.apache.ambari.server.orm.entities.ConfigurationBaseEntity + org.apache.ambari.server.orm.entities.AmbariConfigurationEntity