You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by lp...@apache.org on 2017/09/14 14:38:37 UTC

[01/38] ambari git commit: AMBARI-21922. Allow SERVER Type Alerts To Run For Any Service/Component (amagyar) [Forced Update!]

Repository: ambari
Updated Branches:
  refs/heads/feature-branch-AMBARI-21307 ac3b69628 -> ac71c44c5 (forced update)


AMBARI-21922. Allow SERVER Type Alerts To Run For Any Service/Component (amagyar)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/252e9898
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/252e9898
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/252e9898

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 252e9898c7e68a94924f63549b45af528d15ad14
Parents: c241b9a
Author: Attila Magyar <am...@hortonworks.com>
Authored: Tue Sep 12 13:12:37 2017 +0200
Committer: Attila Magyar <am...@hortonworks.com>
Committed: Tue Sep 12 13:13:51 2017 +0200

----------------------------------------------------------------------
 .../server/orm/dao/AlertDefinitionDAO.java      | 13 +++++++++++++
 .../orm/entities/AlertDefinitionEntity.java     |  4 ++--
 .../services/AmbariServerAlertService.java      | 20 ++++----------------
 .../server/orm/dao/AlertDefinitionDAOTest.java  |  6 ++++++
 4 files changed, 25 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/252e9898/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
index d71429c..cda03f3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
@@ -37,6 +37,7 @@ import org.apache.ambari.server.orm.entities.AlertGroupEntity;
 import org.apache.ambari.server.state.alert.AlertDefinition;
 import org.apache.ambari.server.state.alert.AlertDefinitionFactory;
 import org.apache.ambari.server.state.alert.Scope;
+import org.apache.ambari.server.state.alert.SourceType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -308,6 +309,18 @@ public class AlertDefinitionDAO {
   }
 
   /**
+   * @return all definitions with the given sourceType
+   */
+  @RequiresSession
+  public List<AlertDefinitionEntity> findBySourceType(Long clusterId, SourceType sourceType) {
+    return daoUtils.selectList(
+      entityManagerProvider.get()
+        .createNamedQuery("AlertDefinitionEntity.findBySourceType", AlertDefinitionEntity.class)
+        .setParameter("clusterId", clusterId)
+        .setParameter("sourceType", sourceType));
+  }
+
+  /**
    * Persists a new alert definition, also creating the associated
    * {@link AlertGroupEntity} relationship for the definition's service default
    * group. Fires an {@link AlertDefinitionRegistrationEvent}.

http://git-wip-us.apache.org/repos/asf/ambari/blob/252e9898/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
index de203be..2f4941b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
@@ -72,8 +72,8 @@ import org.apache.ambari.server.state.alert.SourceType;
   @NamedQuery(name = "AlertDefinitionEntity.findByService", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName = :serviceName AND ad.clusterId = :clusterId"),
   @NamedQuery(name = "AlertDefinitionEntity.findByServiceAndComponent", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName = :serviceName AND ad.componentName = :componentName AND ad.clusterId = :clusterId"),
   @NamedQuery(name = "AlertDefinitionEntity.findByServiceMaster", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName IN :services AND ad.scope = :scope AND ad.clusterId = :clusterId AND ad.componentName IS NULL"),
-  @NamedQuery(name = "AlertDefinitionEntity.findByIds", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.definitionId IN :definitionIds")})
-
+  @NamedQuery(name = "AlertDefinitionEntity.findByIds", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.definitionId IN :definitionIds"),
+  @NamedQuery(name = "AlertDefinitionEntity.findBySourceType", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.clusterId = :clusterId AND ad.sourceType = :sourceType")})
 public class AlertDefinitionEntity {
 
   @Id

http://git-wip-us.apache.org/repos/asf/ambari/blob/252e9898/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
index b8058c8..f5d811d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
@@ -113,28 +113,18 @@ public class AmbariServerAlertService extends AbstractScheduledService {
   /**
    * {@inheritDoc}
    * <p/>
-   * Loads all of the {@link Components#AMBARI_SERVER} definitions and schedules
+   * Loads all of the definitions with SERVER source type and schedules
    * the ones that are enabled.
    */
   @Override
   protected void startUp() throws Exception {
     Map<String, Cluster> clusterMap = m_clustersProvider.get().getClusters();
     for (Cluster cluster : clusterMap.values()) {
-      List<AlertDefinitionEntity> entities = m_dao.findByServiceComponent(
-          cluster.getClusterId(), Services.AMBARI.name(),
-          Components.AMBARI_SERVER.name());
-
-      for (AlertDefinitionEntity entity : entities) {
+      for (AlertDefinitionEntity entity : m_dao.findBySourceType(cluster.getClusterId(), SourceType.SERVER)) {
         // don't schedule disabled alert definitions
         if (!entity.getEnabled()) {
           continue;
         }
-
-        SourceType sourceType = entity.getSourceType();
-        if (sourceType != SourceType.SERVER) {
-          continue;
-        }
-
         // schedule the Runnable for the definition
         scheduleRunnable(entity);
       }
@@ -152,10 +142,8 @@ public class AmbariServerAlertService extends AbstractScheduledService {
   protected void runOneIteration() throws Exception {
     Map<String, Cluster> clusterMap = m_clustersProvider.get().getClusters();
     for (Cluster cluster : clusterMap.values()) {
-      // get all of the cluster alerts for AMBARI/AMBARI_SERVER
-      List<AlertDefinitionEntity> entities = m_dao.findByServiceComponent(
-          cluster.getClusterId(), Services.AMBARI.name(),
-          Components.AMBARI_SERVER.name());
+      // get all of the cluster alerts with SERVER source type
+      List<AlertDefinitionEntity> entities = m_dao.findBySourceType(cluster.getClusterId(), SourceType.SERVER);
 
       // for each alert, check to see if it's scheduled correctly
       for (AlertDefinitionEntity entity : entities) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/252e9898/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
index 33d9b3d..d559e0c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
@@ -279,6 +279,12 @@ public class AlertDefinitionDAOTest {
   }
 
   @Test
+  public void testFindBySourceType() throws Exception {
+    assertEquals(15, dao.findBySourceType(clusterId, SourceType.SCRIPT).size());
+    assertEquals(0, dao.findBySourceType(clusterId, SourceType.METRIC).size());
+  }
+
+  @Test
   public void testRefresh() {
   }
 


[08/38] ambari git commit: AMBARI-21932. Some clients are being additionally installed via Add service wizard.(jaimin)

Posted by lp...@apache.org.
AMBARI-21932. Some clients are being additionally installed via Add service wizard.(jaimin)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/9316ea85
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/9316ea85
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/9316ea85

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 9316ea858991552a13481f9d2dab3273e73565f2
Parents: aaf6f0a
Author: Jaimin Jetly <ja...@hortonworks.com>
Authored: Tue Sep 12 11:00:25 2017 -0700
Committer: Jaimin Jetly <ja...@hortonworks.com>
Committed: Tue Sep 12 11:02:12 2017 -0700

----------------------------------------------------------------------
 ambari-web/app/controllers/wizard/step8_controller.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/9316ea85/ambari-web/app/controllers/wizard/step8_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step8_controller.js b/ambari-web/app/controllers/wizard/step8_controller.js
index cc06b5b..b99c6e3 100644
--- a/ambari-web/app/controllers/wizard/step8_controller.js
+++ b/ambari-web/app/controllers/wizard/step8_controller.js
@@ -1333,7 +1333,8 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz
           clientsToClientMap[_clientName].forEach(function (componentName) {
             clientHosts.forEach(function (_clientHost) {
               var host = this.get('content.hosts')[_clientHost.hostName];
-              if (host.isInstalled && !host.hostComponents.someProperty('HostRoles.component_name', componentName)) {
+              var isClientSelected = clients.someProperty('component_name', componentName);
+              if (host.isInstalled && isClientSelected && !host.hostComponents.someProperty('HostRoles.component_name', componentName)) {
                 hostNames.pushObject(_clientHost.hostName);
               }
             }, this);


[25/38] ambari git commit: AMBARI-21307 Rest resource for supporting ambari configurations

Posted by lp...@apache.org.
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/a02052d5
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/a02052d5
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/a02052d5

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: a02052d5d96344e68cf943764b1e93a056c91ecc
Parents: df3a66d
Author: lpuskas <lp...@apache.org>
Authored: Wed Jul 5 14:20:18 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:29 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/a02052d5/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/a02052d5/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:
+ *
+ * <pre>
+ *      {
+ *        "AmbariConfiguration": {
+ *            "type": "ldap-configuration",
+ *            "data": [
+ *                {
+ *                 "authentication.ldap.primaryUrl": "localhost:33389"
+ *                },
+ *                {
+ *                "authentication.ldap.secondaryUrl": "localhost:333"
+ *                 },
+ *                 {
+ *                 "authentication.ldap.baseDn": "dc=ambari,dc=apache,dc=org"
+ *                 }
+ *                 // ......
+ *             ]
+ *         }
+ *     }
+ * </pre>
+ */
+@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/a02052d5/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 1cd2d10..1501a01 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
@@ -224,7 +224,7 @@ public abstract class AbstractProviderModule implements ProviderModule,
    * are going to work unless refactoring is complete.
    */
   @Inject
-  AmbariManagementController managementController;
+  protected AmbariManagementController managementController;
 
   @Inject
   TimelineMetricCacheProvider metricCacheProvider;

http://git-wip-us.apache.org/repos/asf/ambari/blob/a02052d5/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<String> properties = Sets.newHashSet(
+    ResourcePropertyId.ID.getPropertyId(),
+    ResourcePropertyId.TYPE.getPropertyId(),
+    ResourcePropertyId.VERSION.getPropertyId(),
+    ResourcePropertyId.VERSION_TAG.getPropertyId(),
+    ResourcePropertyId.DATA.getPropertyId());
+
+  private static Map<Resource.Type, String> pkPropertyMap = Collections.unmodifiableMap(
+    new HashMap<Resource.Type, String>() {{
+      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<String> 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<Resource> getResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
+    UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    Set<Resource> resources = Sets.newHashSet();
+
+    List<AmbariConfigurationEntity> 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<String> requestedIds) throws AmbariException {
+    Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
+    Set<Map<String, String>> 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<String, Object> 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/a02052d5/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<String>               propertyIds    = PropertyHelper.getPropertyIds(type);
-    Map<Resource.Type,String> keyPropertyIds = PropertyHelper.getKeyPropertyIds(type);
+
+    LOGGER.debug("Creating resource provider for the type: {}", type);
+    Set<String> propertyIds = PropertyHelper.getPropertyIds(type);
+    Map<Resource.Type, String> 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/a02052d5/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/a02052d5/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<EntityManager> 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<AmbariConfigurationEntity> findAll() {
+    TypedQuery<AmbariConfigurationEntity> 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/a02052d5/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/a02052d5/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/a02052d5/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<RoleAuthorization> 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<RoleAuthorization> 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<RoleAuthorization> 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<RoleAuthorization> 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/a02052d5/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 355ee80..8550c2b 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,
@@ -1089,6 +1107,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
@@ -1173,6 +1192,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
@@ -1378,6 +1398,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/a02052d5/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 @@
     <class>org.apache.ambari.server.orm.entities.KerberosDescriptorEntity</class>
     <class>org.apache.ambari.server.orm.entities.RemoteAmbariClusterEntity</class>
     <class>org.apache.ambari.server.orm.entities.RemoteAmbariClusterServiceEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ConfigurationBaseEntity</class>
+    <class>org.apache.ambari.server.orm.entities.AmbariConfigurationEntity</class>
 
     <properties>
       <property name="eclipselink.cache.size.default" value="10000" />


[37/38] ambari git commit: AMBARI-21307 implemented user attribute detection. Organized code

Posted by lp...@apache.org.
AMBARI-21307 implemented user attribute detection. Organized code


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7b91bc5b
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7b91bc5b
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7b91bc5b

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 7b91bc5b005493972ea4ad93b1752115414baed4
Parents: e4a80b1
Author: lpuskas <lp...@apache.org>
Authored: Tue Sep 12 08:10:47 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:32 2017 +0200

----------------------------------------------------------------------
 .../services/ldap/LdapConfigurationService.java |   2 +-
 .../server/ldap/AmbariLdapConfiguration.java    |   9 ++
 .../server/ldap/service/AmbariLdapFacade.java   |   2 +-
 .../server/ldap/service/AttributeDetector.java  |  38 ++++++
 .../service/LdapAttributeDetectionService.java  |   7 +-
 .../ambari/server/ldap/service/LdapFacade.java  |   2 +-
 .../server/ldap/service/LdapSearchService.java  |  18 ---
 .../ads/DefaultAttributeDetectionService.java   | 132 ++++++++++++++++++-
 .../ads/DefaultLdapConfigurationService.java    |   2 +-
 .../ldap/service/ads/ObjectClassDetector.java   |  81 ++++++++++++
 .../ads/OccurranceAndWeightBasedDetector.java   |  81 ++++++++++++
 .../service/ads/UserNameAttributeDetector.java  |  75 +++++++++++
 .../DefaultAttributeDetectionServiceTest.java   |  35 ++---
 13 files changed, 440 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
index 1b8427b..66809c3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
@@ -107,7 +107,7 @@ public class LdapConfigurationService extends AmbariConfigurationService {
         case TEST_ATTRIBUTES:
 
           LOGGER.info("Testing LDAP attributes ....");
-          groups = ldapFacade.checkLdapAttibutes(ldapConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
+          groups = ldapFacade.checkLdapAttributes(ldapConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
           setResult(groups, result);
 
           break;

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
index 76faeed..e28c6ed 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
@@ -98,6 +98,10 @@ public class AmbariLdapConfiguration {
     return value;
   }
 
+  public void setValueFor(AmbariLdapConfig ambariLdapConfig, Object value) {
+    configurationMap.put(ambariLdapConfig.key(), value);
+  }
+
   @Inject
   public AmbariLdapConfiguration(@Assisted Map<String, Object> configuration) {
     this.configurationMap = configuration;
@@ -219,4 +223,9 @@ public class AmbariLdapConfiguration {
     return (String) configValue(AmbariLdapConfig.REFERRAL_HANDLING);
   }
 
+
+  @Override
+  public String toString() {
+    return configurationMap.toString();
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
index 16bf6b7..f159418 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
@@ -90,7 +90,7 @@ public class AmbariLdapFacade implements LdapFacade {
   }
 
   @Override
-  public Set<String> checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ldapConfiguration) throws AmbariLdapException {
+  public Set<String> checkLdapAttributes(Map<String, Object> parameters, AmbariLdapConfiguration ldapConfiguration) throws AmbariLdapException {
     String userName = getTestUserNameFromParameters(parameters);
     String testUserPass = getTestUserPasswordFromParameters(parameters);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AttributeDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AttributeDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AttributeDetector.java
new file mode 100644
index 0000000..3e20a6a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AttributeDetector.java
@@ -0,0 +1,38 @@
+/*
+ * 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.ldap.service;
+
+/**
+ * Operations for detecting LDAP related settings.
+ * Attributes and values are detected based on a sample set of results returned from a search
+ */
+public interface AttributeDetector<T> {
+
+  /**
+   * Collects potential attribute names or values from a set of result entries.
+   *
+   * @param entry a result entry returned by a search operation
+   */
+  void collect(T entry);
+
+  /**
+   * Implements the decision based on whiche the "best" possible attribute or value is selected.
+   *
+   * @return the most probable attribute name or value (based on the logic in the implementer)
+   */
+  String detect();
+
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapAttributeDetectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapAttributeDetectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapAttributeDetectionService.java
index 70a8977..4cfa81e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapAttributeDetectionService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapAttributeDetectionService.java
@@ -15,12 +15,11 @@
 package org.apache.ambari.server.ldap.service;
 
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.directory.ldap.client.api.LdapConnection;
 
 /**
  * Contract defining operations to detect user and group attributes.
  */
-public interface LdapAttributeDetectionService {
+public interface LdapAttributeDetectionService<T> {
 
   /**
    * Decorates the passed in configuration with the detected ldap user attribute values
@@ -29,7 +28,7 @@ public interface LdapAttributeDetectionService {
    * @param ambariLdapConfiguration configuration instance holding connection details
    * @return the configuration decorated with user related attributes
    */
-  AmbariLdapConfiguration detectLdapUserAttributes(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration);
+  AmbariLdapConfiguration detectLdapUserAttributes(T ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration);
 
   /**
    * Decorates the passed in configuration with the detected ldap group attribute values
@@ -38,6 +37,6 @@ public interface LdapAttributeDetectionService {
    * @param ambariLdapConfiguration configuration instance holding connection details
    * @return the configuration decorated with group related attributes
    */
-  AmbariLdapConfiguration detectLdapGroupAttributes(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration);
+  AmbariLdapConfiguration detectLdapGroupAttributes(T ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration);
 }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
index 76b16c4..7cd25da 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
@@ -48,5 +48,5 @@ public interface LdapFacade {
    * @param ambariLdapConfiguration configutration instance with available attributes
    * @throws AmbariLdapException if the attribute checking fails
    */
-  Set<String> checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;
+  Set<String> checkLdapAttributes(Map<String, Object> parameters, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java
deleted file mode 100644
index f1abc8b..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * 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.ldap.service;
-
-public interface LdapSearchService {
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
index 55d0765..710adf1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
@@ -14,19 +14,47 @@
 
 package org.apache.ambari.server.ldap.service.ads;
 
+import java.util.Set;
+
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.service.AmbariLdapException;
+import org.apache.ambari.server.ldap.service.AttributeDetector;
 import org.apache.ambari.server.ldap.service.LdapAttributeDetectionService;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.Response;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchResultEntry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.util.Strings;
 import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Sets;
+
 @Singleton
-public class DefaultAttributeDetectionService implements LdapAttributeDetectionService {
+public class DefaultAttributeDetectionService implements LdapAttributeDetectionService<LdapConnection> {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAttributeDetectionService.class);
+  private static final int SAMPLE_RESULT_SIZE = 50;
+
+  // ordered list of possible username attribute values (the most significant valus should be first)
+
+  private static final Set<String> USER_OBJECT_CLASS_VALUES = Sets.newHashSet("person", "posixAccount");
+  private static final Set<String> USER_GROUP_MEMBER_ATTR_VALUES = Sets.newHashSet("memberOf", "ismemberOf");
+
+  @Inject
+  private UserNameAttributeDetector userNameAttrDetector = new UserNameAttributeDetector(); // todo remove instantition
+
+  @Inject
+  private ObjectClassDetector objectClassDetector = new ObjectClassDetector(); // todo remove instantition
 
   @Inject
   public DefaultAttributeDetectionService() {
@@ -36,7 +64,72 @@ public class DefaultAttributeDetectionService implements LdapAttributeDetectionS
   public AmbariLdapConfiguration detectLdapUserAttributes(LdapConnection connection, AmbariLdapConfiguration ambariLdapConfiguration) {
     LOGGER.info("Detecting LDAP user attributes ...");
 
-    return null;
+    // perform a search using the user search base
+    if (Strings.isEmpty(ambariLdapConfiguration.userSearchBase())) {
+      LOGGER.warn("No user search base provided");
+      return ambariLdapConfiguration;
+    }
+
+    SearchCursor searchCursor = null;
+
+    try {
+      // todo should the bind operation be done in the facade?
+      connection.bind(ambariLdapConfiguration.bindDn(), ambariLdapConfiguration.bindPassword());
+
+      SearchRequest searchRequest = assembleSearchRequest(ambariLdapConfiguration);
+
+      // do the search
+      searchCursor = connection.search(searchRequest);
+
+      int processedUserCnt = 0;
+
+      while (searchCursor.next()) {
+
+        if (processedUserCnt >= SAMPLE_RESULT_SIZE) {
+          LOGGER.debug("The maximum count of results for attribute detection has exceeded. Quit user attribute detection.");
+          break;
+        }
+
+        Response response = searchCursor.get();
+        // process the SearchResultEntry
+
+        if (response instanceof SearchResultEntry) {
+          Entry resultEntry = ((SearchResultEntry) response).getEntry();
+          LOGGER.info("Processing sample entry: [{}]", resultEntry.getDn());
+          userNameAttrDetector.collect(resultEntry);
+          objectClassDetector.collect(resultEntry);
+          processedUserCnt++;
+        }
+      }
+
+      ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.USER_NAME_ATTRIBUTE, userNameAttrDetector.detect());
+      ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.USER_OBJECT_CLASS, objectClassDetector.detect());
+
+      LOGGER.info("Decorated ambari ldap config : [{}]", ambariLdapConfiguration);
+
+    } catch (Exception e) {
+
+      LOGGER.error("Ldap operation failed", e);
+    } finally {
+      // housekeeping
+      if (null != searchCursor) {
+        searchCursor.close();
+      }
+    }
+
+    return ambariLdapConfiguration;
+  }
+
+  private void detectUserAttributes(Entry resultEntry, AttributeDetector attributeDetector) {
+
+    attributeDetector.collect(resultEntry);
+
+//    Set<String> objectClasses = detectUserObjectClass(resultEntry);
+//    if (!objectClasses.isEmpty()) {
+//      ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.USER_OBJECT_CLASS, StringUtils.join(objectClasses, ","));
+//    }
+
+
   }
 
   @Override
@@ -44,4 +137,39 @@ public class DefaultAttributeDetectionService implements LdapAttributeDetectionS
     LOGGER.info("Detecting LDAP group attributes ...");
     return null;
   }
+
+  private SearchRequest assembleSearchRequest(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    try {
+
+      SearchRequest req = new SearchRequestImpl();
+      req.setScope(SearchScope.SUBTREE);
+      req.addAttributes("*");
+      req.setTimeLimit(0);
+      req.setBase(new Dn(ambariLdapConfiguration.userSearchBase()));
+      // the filter must be set!
+      req.setFilter(FilterBuilder.present(ambariLdapConfiguration.dnAttribute()).toString());
+
+      return req;
+
+    } catch (Exception e) {
+      LOGGER.error("Could not assemble ldap search request", e);
+      throw new AmbariLdapException(e);
+    }
+  }
+
+
+  private Set<String> detectUserObjectClass(Entry entry) {
+    LOGGER.info("Detecting user object class. Attributes: {}", entry.getAttributes());
+    throw new UnsupportedOperationException("Not yet implemented");
+  }
+
+  private String detectGroupNameAttribute(Entry entry) {
+    throw new UnsupportedOperationException("Not yet implemented");
+  }
+
+  private Set<String> detectGroupObjectClass(Entry entry) {
+    throw new UnsupportedOperationException("Not yet implemented");
+  }
+
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
index db8c77f..fa2e44b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
@@ -190,7 +190,7 @@ public class DefaultLdapConfigurationService implements LdapConfigurationService
       LOGGER.debug("Anonimous binding not supported, binding with the manager detailas...");
       connection.bind(ambariLdapConfiguration.bindDn(), ambariLdapConfiguration.bindPassword());
     } else {
-      LOGGER.debug("Binding anonimously ...");
+      LOGGER.debug("Binding anonymously ...");
       connection.bind();
     }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/ObjectClassDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/ObjectClassDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/ObjectClassDetector.java
new file mode 100644
index 0000000..2613517
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/ObjectClassDetector.java
@@ -0,0 +1,81 @@
+/*
+ * 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.ldap.service.ads;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class ObjectClassDetector extends OccurranceAndWeightBasedDetector {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(ObjectClassDetector.class);
+  private Map<String, Integer> occurranceMap = Maps.newHashMap();
+  private Map<String, Integer> weightsMap = Maps.newHashMap();
+
+
+  private enum ObjectClassValue {
+    PERSON("person", 1),
+    POSIX_ACCOUNT("posixAccount", 1);
+
+    private String ocVal;
+    private Integer weight;
+
+    ObjectClassValue(String attr, Integer weght) {
+      this.ocVal = attr;
+      this.weight = weght;
+    }
+
+    Integer weight() {
+      return this.weight;
+    }
+
+    String ocVal() {
+      return this.ocVal;
+    }
+
+  }
+
+  @Inject
+  public ObjectClassDetector() {
+    for (ObjectClassValue ocVal : ObjectClassValue.values()) {
+      occurranceMap.put(ocVal.ocVal(), 0);
+      weightsMap.put(ocVal.ocVal(), ocVal.weight());
+    }
+
+  }
+
+  @Override
+  protected Map<String, Integer> occurranceMap() {
+    return occurranceMap;
+  }
+
+  @Override
+  protected Map<String, Integer> weightsMap() {
+    return weightsMap;
+  }
+
+  @Override
+  protected boolean applies(Entry entry, String value) {
+    LOGGER.info("Checking for object class [{}] in entry [{}]", value, entry.getDn());
+    return entry.hasObjectClass(value);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/OccurranceAndWeightBasedDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/OccurranceAndWeightBasedDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/OccurranceAndWeightBasedDetector.java
new file mode 100644
index 0000000..32dc238
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/OccurranceAndWeightBasedDetector.java
@@ -0,0 +1,81 @@
+/*
+ * 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.ldap.service.ads;
+
+import java.util.Map;
+
+import org.apache.ambari.server.ldap.service.AttributeDetector;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class OccurranceAndWeightBasedDetector implements AttributeDetector<Entry> {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(OccurranceAndWeightBasedDetector.class);
+
+  protected abstract Map<String, Integer> occurranceMap();
+
+  protected abstract Map<String, Integer> weightsMap();
+
+  protected abstract boolean applies(Entry entry, String value);
+
+  @Override
+  public String detect() {
+    Map.Entry<String, Integer> selectedEntry = null;
+
+    for (Map.Entry<String, Integer> entry : occurranceMap().entrySet()) {
+      if (selectedEntry == null) {
+
+        selectedEntry = entry;
+        LOGGER.info("Initial name attribute: {}", selectedEntry);
+        continue;
+
+      }
+
+      if (selectedEntry.getValue() < entry.getValue()) {
+
+        LOGGER.info("Changing potential name attribute from : [{}] to: [{}]", selectedEntry, entry);
+        selectedEntry = entry;
+
+      }
+    }
+    return selectedEntry.getKey();
+  }
+
+  @Override
+  public void collect(Entry entry) {
+    LOGGER.info("Detecting ldap attributes/values ...");
+
+    for (String attributeValue : occurranceMap().keySet()) {
+      if (applies(entry, attributeValue)) {
+
+        Integer cnt = occurranceMap().get(attributeValue).intValue();
+        if (weightsMap().containsKey(attributeValue)) {
+          cnt = cnt + weightsMap().get(attributeValue);
+        } else {
+          cnt = cnt + 1;
+        }
+        occurranceMap().put(attributeValue, cnt);
+
+        LOGGER.info("Collected potential name attr: {}, count: {}", attributeValue, cnt);
+
+      } else {
+        LOGGER.info("The result entry doesn't contain the attribute: [{}]", attributeValue);
+      }
+    }
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/UserNameAttributeDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/UserNameAttributeDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/UserNameAttributeDetector.java
new file mode 100644
index 0000000..bbb4b43
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/UserNameAttributeDetector.java
@@ -0,0 +1,75 @@
+/*
+ * 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.ldap.service.ads;
+
+import java.util.Map;
+
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class UserNameAttributeDetector extends OccurranceAndWeightBasedDetector {
+  private static final Logger LOGGER = LoggerFactory.getLogger(UserNameAttributeDetector.class);
+
+  private Map<String, Integer> occurranceMap = Maps.newHashMap();
+  private Map<String, Integer> weightsMap = Maps.newHashMap();
+
+  private enum NameAttrs {
+    SAM_ACCOUNT_NAME("sAMAccountName", 5),
+    UID("uid", 3),
+    CN("cn", 1);
+
+    private String attrName;
+    private Integer weight;
+
+    NameAttrs(String attr, Integer weght) {
+      this.attrName = attr;
+      this.weight = weght;
+    }
+
+    Integer weight() {
+      return this.weight;
+    }
+
+    String attrName() {
+      return this.attrName;
+    }
+
+  }
+
+  public UserNameAttributeDetector() {
+    for (NameAttrs nameAttr : NameAttrs.values()) {
+      occurranceMap.put(nameAttr.attrName(), 0);
+      weightsMap.put(nameAttr.attrName(), nameAttr.weight());
+    }
+  }
+
+  protected Map<String, Integer> occurranceMap() {
+    return occurranceMap;
+  }
+
+  protected Map<String, Integer> weightsMap() {
+    return weightsMap;
+  }
+
+  @Override
+  protected boolean applies(Entry entry, String value) {
+    LOGGER.info("Checking for attribute  [{}] in entry [{}]", value, entry.getDn());
+    return entry.containsAttribute(value);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7b91bc5b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
index 5b3ac20..5cddf1a 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
@@ -69,13 +69,31 @@ public class DefaultAttributeDetectionServiceTest {
   }
 
 
+  @Test
+  public void functionalTest() throws Exception {
+    // GIVEN
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(getTestPropertiesMap());
+    LdapConnectionService connectionService = new DefaultLdapConnectionService();
+    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
+
+    // WHEN
+    AmbariLdapConfiguration config = attributeDetectionService.detectLdapUserAttributes(ldapConnection, ambariLdapConfiguration);
+
+    // THEN
+
+    ldapConnection.close();
+
+  }
+
   private Map<String, Object> getTestPropertiesMap() {
     Map<String, Object> ldapPropsMap = Maps.newHashMap();
 
     ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.ANONYMOUS_BIND.key(), "true");
     ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.SERVER_HOST.key(), "ldap.forumsys.com");
     ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.SERVER_PORT.key(), "389");
-    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.BIND_DN.key(), "dc=example,dc=com");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.BIND_DN.key(), "cn=read-only-admin,dc=example,dc=com");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.BIND_PASSWORD.key(), "password");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.DN_ATTRIBUTE.key(), SchemaConstants.CN_AT);
 
     ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_OBJECT_CLASS.key(), SchemaConstants.PERSON_OC);
     ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_NAME_ATTRIBUTE.key(), SchemaConstants.UID_AT);
@@ -84,19 +102,4 @@ public class DefaultAttributeDetectionServiceTest {
     return ldapPropsMap;
 
   }
-
-  @Test
-  public void functionalTest() throws Exception {
-    // GIVEN
-    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(getTestPropertiesMap());
-    LdapConnectionService connectionService = new DefaultLdapConnectionService();
-    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
-
-
-    // WHEN
-    AmbariLdapConfiguration config = attributeDetectionService.detectLdapUserAttributes(ldapConnection, ambariLdapConfiguration);
-
-    // THEN
-
-  }
 }
\ No newline at end of file


[35/38] ambari git commit: AMBARI-21307 renamed package, minor corrections. Changed endpoint name

Posted by lp...@apache.org.
AMBARI-21307 renamed package, minor corrections. Changed endpoint name


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c87043c9
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c87043c9
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c87043c9

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: c87043c9befee2424dafb2a951580140441e89a8
Parents: a7757b2
Author: lpuskas <lp...@apache.org>
Authored: Mon Aug 14 13:21:07 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:31 2017 +0200

----------------------------------------------------------------------
 .../services/AmbariConfigurationService.java    |   2 +-
 .../api/services/ldap/LdapRestService.java      |  15 +-
 .../server/ldap/AmbariLdapConfiguration.java    |   5 +-
 .../apache/ambari/server/ldap/LdapModule.java   |   4 +-
 ...efaultLdapConfigurationValidatorService.java | 243 -------------------
 .../ad/DefaultLdapConnectionService.java        |  63 -----
 ...efaultLdapConfigurationValidatorService.java | 243 +++++++++++++++++++
 .../ads/DefaultLdapConnectionService.java       |  63 +++++
 ...ltLdapConfigurationValidatorServiceTest.java | 113 ---------
 ...ltLdapConfigurationValidatorServiceTest.java | 113 +++++++++
 10 files changed, 435 insertions(+), 429 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c87043c9/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
index 927e518..492509f 100644
--- 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
@@ -63,7 +63,7 @@ import io.swagger.annotations.ApiResponses;
  *     }
  * </pre>
  */
-@Path("/configurations/")
+@Path("/ambariconfigs/")
 @Api(value = "Ambari Configurations", description = "Endpoint for Ambari configuration related operations")
 public class AmbariConfigurationService extends BaseService {
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c87043c9/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
index 8578204..4e654dc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
@@ -34,6 +34,7 @@ import javax.inject.Inject;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
@@ -70,8 +71,9 @@ public class LdapRestService extends BaseService {
 
   @POST
   @ApiIgnore // until documented
-  @Path("/action") // todo this needs to be moved under the resource
+  @Path("/validate") // todo this needs to be moved under the resource
   @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
   public Response validateConfiguration(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
 
     Set<String> groups = Sets.newHashSet();
@@ -95,10 +97,7 @@ public class LdapRestService extends BaseService {
 
           LOGGER.info("Testing LDAP attributes ....");
           groups = ldapFacade.checkLdapAttibutes(ldapCheckConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
-          // todo factor out the resource creation, design better the structure in the response
-          Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
-          resource.setProperty("groups", groups);
-          result.getResultTree().addChild(resource, "payload");
+          setResult(groups, result);
 
           break;
         case "detect-attributes":
@@ -119,6 +118,12 @@ public class LdapRestService extends BaseService {
     return Response.status(result.getStatus().getStatusCode()).entity(getResultSerializer().serialize(result)).build();
   }
 
+  private void setResult(Set<String> groups, Result result) {
+    Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
+    resource.setProperty("groups", groups);
+    result.getResultTree().addChild(resource, "payload");
+  }
+
   private void validateRequest(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
     String errMsg;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c87043c9/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
index 8ab587b..b1cbced 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
@@ -37,11 +37,12 @@ public class AmbariLdapConfiguration {
   public enum LdapConfigProperty {
     LDAP_CONFIGURED("ambari.ldap.configured"),
     AUTOMATIC_ATTRIBUTE_DETECTION("ambari.ldap.automatic.attribute.detection"),
-
     USE_SSL("ambari.ldap.usessl"),
     LDAP_SERVER_HOST("ambari.ldap.server.host"),
     LDAP_SERVER_PORT("ambari.ldap.server.port"),
-    BASE_DN("ambari.ldap.base.dn"),
+    LDAP_TRUSTSTORE_TYPE("ambari.ldap.truststore.type"),
+    LDAP_TRUSTSTORE_PATH("ambari.ldap.truststore.path"),
+    BASE_DN("ambari.ldap.bind.dn"),
 
     BIND_ANONIMOUSLY("ambari.ldap.bindanonymously"),
     MANAGER_DN("ambari.ldap.managerdn"),

http://git-wip-us.apache.org/repos/asf/ambari/blob/c87043c9/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
index 1b49159..a4ad2ee 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
@@ -18,8 +18,8 @@ package org.apache.ambari.server.ldap;
 import org.apache.ambari.server.ldap.service.AmbariLdapFacade;
 import org.apache.ambari.server.ldap.service.LdapConnectionService;
 import org.apache.ambari.server.ldap.service.LdapFacade;
-import org.apache.ambari.server.ldap.service.ad.DefaultLdapConfigurationValidatorService;
-import org.apache.ambari.server.ldap.service.ad.DefaultLdapConnectionService;
+import org.apache.ambari.server.ldap.service.ads.DefaultLdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.service.ads.DefaultLdapConnectionService;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.assistedinject.FactoryModuleBuilder;

http://git-wip-us.apache.org/repos/asf/ambari/blob/c87043c9/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java
deleted file mode 100644
index a8503ca..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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.ldap.service.ad;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
-import org.apache.ambari.server.ldap.service.AmbariLdapException;
-import org.apache.ambari.server.ldap.service.LdapConnectionService;
-import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator;
-import org.apache.directory.api.ldap.model.cursor.EntryCursor;
-import org.apache.directory.api.ldap.model.cursor.SearchCursor;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.message.Response;
-import org.apache.directory.api.ldap.model.message.SearchRequest;
-import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
-import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.ldap.client.api.LdapConnection;
-import org.apache.directory.ldap.client.api.search.FilterBuilder;
-import org.apache.directory.shared.ldap.constants.SchemaConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-/**
- * Implementation of the validation logic using the Apache Directory API.
- */
-@Singleton
-public class DefaultLdapConfigurationValidatorService implements LdapConfigurationValidatorService {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class);
-
-  @Inject
-  private LdapConnectionService ldapConnectionService;
-
-  /**
-   * Facilitating the instantiation
-   */
-  @Inject
-  public DefaultLdapConfigurationValidatorService() {
-  }
-
-  @Override
-  public void checkConnection(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
-    try {
-      bind(ambariLdapConfiguration, ldapConnection);
-    } catch (LdapException e) {
-      LOGGER.error("Could not connect to the LDAP server", e);
-      throw new AmbariLdapException(e);
-    }
-  }
-
-
-  /**
-   * Checks the user attributes provided in the configuration instance by issuing a search for a (known) test user in the LDAP.
-   * Attributes are considered correct if there is at least one entry found.
-   *
-   * Invalid attributes are signaled by throwing an exception.
-   *
-   * @param testUserName            the test username
-   * @param testPassword            the test password
-   * @param ambariLdapConfiguration configuration instance holding ldap configuration details
-   * @return the DN of the test user
-   * @throws AmbariException if the attributes are not valid or any errors occurs
-   */
-  @Override
-  public String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
-    SearchCursor searchCursor = null;
-    String userDn = null;
-    try {
-      LOGGER.info("Checking user attributes for user {} r ...", testUserName);
-
-      // bind anonimously or with manager data
-      bind(ambariLdapConfiguration, ldapConnection);
-
-      // set up a filter based on the provided attributes
-      String filter = FilterBuilder.and(
-        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
-        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), testUserName))
-        .toString();
-
-      LOGGER.info("Searching for the user: {} using the search filter: {}", testUserName, filter);
-      EntryCursor entryCursor = ldapConnection.search(new Dn(ambariLdapConfiguration.userSearchBase()), filter, SearchScope.SUBTREE);
-
-      // collecting search result entries
-      List<Entry> users = Lists.newArrayList();
-      for (Entry entry : entryCursor) {
-        users.add(entry);
-        userDn = entry.getDn().getNormName();
-      }
-
-      // there should be at least one user found
-      if (users.isEmpty()) {
-        String msg = String.format("There are no users found using the filter: [ %s ]. Try changing the attribute values", filter);
-        LOGGER.error(msg);
-        throw new Exception(msg);
-      }
-
-      LOGGER.info("Attibute validation succeeded. Filter: {}", filter);
-
-    } catch (Exception e) {
-
-      LOGGER.error("User attributes validation failed.", e);
-      throw new AmbariLdapException(e.getMessage(), e);
-
-    } finally {
-      closeResources(ldapConnection, searchCursor);
-    }
-    return userDn;
-  }
-
-
-  @Override
-  public Set<String> checkGroupAttributes(LdapConnection ldapConnection, String userDn, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
-    SearchCursor searchCursor = null;
-    Set<Response> groupResponses = Sets.newHashSet();
-
-    try {
-      LOGGER.info("Checking group attributes for user dn {} ...", userDn);
-
-      bind(ambariLdapConfiguration, ldapConnection);
-
-      // set up a filter based on the provided attributes
-      String filter = FilterBuilder.and(
-        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.groupObjectClass()),
-        FilterBuilder.equal(ambariLdapConfiguration.groupMemberAttribute(), userDn)
-      ).toString();
-
-      LOGGER.info("Searching for the groups the user dn: {} is member of using the search filter: {}", userDn, filter);
-
-      // assemble a search request
-      SearchRequest searchRequest = new SearchRequestImpl();
-      searchRequest.setFilter(filter);
-      searchRequest.setBase(new Dn(ambariLdapConfiguration.groupSearchBase()));
-      searchRequest.setScope(SearchScope.SUBTREE);
-      searchRequest.addAttributes(ambariLdapConfiguration.groupMemberAttribute(), ambariLdapConfiguration.groupNameAttribute());
-
-      // perform the search
-      searchCursor = ldapConnection.search(searchRequest);
-
-      for (Response response : searchCursor) {
-        groupResponses.add(response);
-      }
-
-    } catch (Exception e) {
-
-      LOGGER.error("User attributes validation failed.", e);
-      throw new AmbariLdapException(e.getMessage(), e);
-
-    } finally {
-      closeResources(ldapConnection, searchCursor);
-    }
-
-    return processGroupResults(groupResponses, ambariLdapConfiguration);
-  }
-
-  /**
-   * Binds to the LDAP server (anonimously or wit manager credentials)
-   *
-   * @param ambariLdapConfiguration configuration instance
-   * @param connection              connection instance
-   * @throws LdapException if the bind operation fails
-   */
-  private void bind(AmbariLdapConfiguration ambariLdapConfiguration, LdapConnection connection) throws LdapException {
-    LOGGER.info("Connecting to LDAP ....");
-    if (!ambariLdapConfiguration.bindAnonimously()) {
-      LOGGER.debug("Anonimous binding not supported, binding with the manager detailas...");
-      connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
-    } else {
-      LOGGER.debug("Binding anonimously ...");
-      connection.bind();
-    }
-
-    if (!connection.isConnected()) {
-      LOGGER.error("Not connected to the LDAP server. Connection instance: {}", connection);
-      throw new IllegalStateException("The connection to the LDAP server is not alive");
-    }
-    LOGGER.info("Connected to LDAP.");
-  }
-
-
-  /**
-   * Extracts meaningful values from the search result.
-   *
-   * @param groupResponses          the result entries returned by the search
-   * @param ambariLdapConfiguration holds the keys of the meaningful attributes
-   * @return a set with the group names the test user belongs to
-   */
-  private Set<String> processGroupResults(Set<Response> groupResponses, AmbariLdapConfiguration ambariLdapConfiguration) {
-    Set<String> groupStrSet = Sets.newHashSet();
-    for (Response response : groupResponses) {
-      Entry entry = ((SearchResultEntryDecorator) response).getEntry();
-      groupStrSet.add(entry.get(ambariLdapConfiguration.groupNameAttribute()).get().getString());
-    }
-
-    LOGGER.debug("Extracted group names from group search responses: {}", groupStrSet);
-    return groupStrSet;
-  }
-
-  private void closeResources(LdapConnection connection, SearchCursor searchCursor) {
-    LOGGER.debug("Housekeeping: closing the connection and the search cursor ...");
-
-    if (null != searchCursor) {
-      // this method is idempotent
-      searchCursor.close();
-    }
-
-    if (null != connection) {
-      try {
-        connection.close();
-      } catch (IOException e) {
-        LOGGER.error("Exception occurred while closing the connection", e);
-      }
-    }
-  }
-
-}
-
-
-

http://git-wip-us.apache.org/repos/asf/ambari/blob/c87043c9/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java
deleted file mode 100644
index 25dc1f2..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * 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.ldap.service.ad;
-
-import javax.inject.Singleton;
-
-import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.service.LdapConnectionService;
-import org.apache.directory.ldap.client.api.LdapConnectionConfig;
-import org.apache.directory.ldap.client.api.LdapNetworkConnection;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Singleton
-public class DefaultLdapConnectionService implements LdapConnectionService {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConnectionService.class);
-
-  @Override
-  public LdapNetworkConnection createLdapConnection(AmbariLdapConfiguration ambariLdapConfiguration) {
-    LOGGER.debug("Creating ldap connection instance from: {}", ambariLdapConfiguration);
-    return new LdapNetworkConnection(getLdapConnectionConfig(ambariLdapConfiguration));
-  }
-
-  private LdapConnectionConfig getLdapConnectionConfig(AmbariLdapConfiguration ambariAmbariLdapConfiguration) {
-    LOGGER.debug("Creating a configuration instance based on the ambari configuration: {}", ambariAmbariLdapConfiguration);
-
-    LdapConnectionConfig ldapConnectionConfig = new LdapConnectionConfig();
-    ldapConnectionConfig.setLdapHost(ambariAmbariLdapConfiguration.ldapServerHost());
-    ldapConnectionConfig.setLdapPort(ambariAmbariLdapConfiguration.ldapServerPort());
-    ldapConnectionConfig.setUseSsl(ambariAmbariLdapConfiguration.useSSL());
-
-    // todo set the other values as required
-    return ldapConnectionConfig;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c87043c9/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java
new file mode 100644
index 0000000..040983a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java
@@ -0,0 +1,243 @@
+/*
+ * 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.ldap.service.ads;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.service.AmbariLdapException;
+import org.apache.ambari.server.ldap.service.LdapConnectionService;
+import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator;
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.Response;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Implementation of the validation logic using the Apache Directory API.
+ */
+@Singleton
+public class DefaultLdapConfigurationValidatorService implements LdapConfigurationValidatorService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class);
+
+  @Inject
+  private LdapConnectionService ldapConnectionService;
+
+  /**
+   * Facilitating the instantiation
+   */
+  @Inject
+  public DefaultLdapConfigurationValidatorService() {
+  }
+
+  @Override
+  public void checkConnection(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    try {
+      bind(ambariLdapConfiguration, ldapConnection);
+    } catch (LdapException e) {
+      LOGGER.error("Could not connect to the LDAP server", e);
+      throw new AmbariLdapException(e);
+    }
+  }
+
+
+  /**
+   * Checks the user attributes provided in the configuration instance by issuing a search for a (known) test user in the LDAP.
+   * Attributes are considered correct if there is at least one entry found.
+   *
+   * Invalid attributes are signaled by throwing an exception.
+   *
+   * @param testUserName            the test username
+   * @param testPassword            the test password
+   * @param ambariLdapConfiguration configuration instance holding ldap configuration details
+   * @return the DN of the test user
+   * @throws AmbariException if the attributes are not valid or any errors occurs
+   */
+  @Override
+  public String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    SearchCursor searchCursor = null;
+    String userDn = null;
+    try {
+      LOGGER.info("Checking user attributes for user {} r ...", testUserName);
+
+      // bind anonimously or with manager data
+      bind(ambariLdapConfiguration, ldapConnection);
+
+      // set up a filter based on the provided attributes
+      String filter = FilterBuilder.and(
+        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
+        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), testUserName))
+        .toString();
+
+      LOGGER.info("Searching for the user: {} using the search filter: {}", testUserName, filter);
+      EntryCursor entryCursor = ldapConnection.search(new Dn(ambariLdapConfiguration.userSearchBase()), filter, SearchScope.SUBTREE);
+
+      // collecting search result entries
+      List<Entry> users = Lists.newArrayList();
+      for (Entry entry : entryCursor) {
+        users.add(entry);
+        userDn = entry.getDn().getNormName();
+      }
+
+      // there should be at least one user found
+      if (users.isEmpty()) {
+        String msg = String.format("There are no users found using the filter: [ %s ]. Try changing the attribute values", filter);
+        LOGGER.error(msg);
+        throw new Exception(msg);
+      }
+
+      LOGGER.info("Attibute validation succeeded. Filter: {}", filter);
+
+    } catch (Exception e) {
+
+      LOGGER.error("User attributes validation failed.", e);
+      throw new AmbariLdapException(e.getMessage(), e);
+
+    } finally {
+      closeResources(ldapConnection, searchCursor);
+    }
+    return userDn;
+  }
+
+
+  @Override
+  public Set<String> checkGroupAttributes(LdapConnection ldapConnection, String userDn, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    SearchCursor searchCursor = null;
+    Set<Response> groupResponses = Sets.newHashSet();
+
+    try {
+      LOGGER.info("Checking group attributes for user dn {} ...", userDn);
+
+      bind(ambariLdapConfiguration, ldapConnection);
+
+      // set up a filter based on the provided attributes
+      String filter = FilterBuilder.and(
+        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.groupObjectClass()),
+        FilterBuilder.equal(ambariLdapConfiguration.groupMemberAttribute(), userDn)
+      ).toString();
+
+      LOGGER.info("Searching for the groups the user dn: {} is member of using the search filter: {}", userDn, filter);
+
+      // assemble a search request
+      SearchRequest searchRequest = new SearchRequestImpl();
+      searchRequest.setFilter(filter);
+      searchRequest.setBase(new Dn(ambariLdapConfiguration.groupSearchBase()));
+      searchRequest.setScope(SearchScope.SUBTREE);
+      searchRequest.addAttributes(ambariLdapConfiguration.groupMemberAttribute(), ambariLdapConfiguration.groupNameAttribute());
+
+      // perform the search
+      searchCursor = ldapConnection.search(searchRequest);
+
+      for (Response response : searchCursor) {
+        groupResponses.add(response);
+      }
+
+    } catch (Exception e) {
+
+      LOGGER.error("User attributes validation failed.", e);
+      throw new AmbariLdapException(e.getMessage(), e);
+
+    } finally {
+      closeResources(ldapConnection, searchCursor);
+    }
+
+    return processGroupResults(groupResponses, ambariLdapConfiguration);
+  }
+
+  /**
+   * Binds to the LDAP server (anonimously or wit manager credentials)
+   *
+   * @param ambariLdapConfiguration configuration instance
+   * @param connection              connection instance
+   * @throws LdapException if the bind operation fails
+   */
+  private void bind(AmbariLdapConfiguration ambariLdapConfiguration, LdapConnection connection) throws LdapException {
+    LOGGER.info("Connecting to LDAP ....");
+    if (!ambariLdapConfiguration.bindAnonimously()) {
+      LOGGER.debug("Anonimous binding not supported, binding with the manager detailas...");
+      connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
+    } else {
+      LOGGER.debug("Binding anonimously ...");
+      connection.bind();
+    }
+
+    if (!connection.isConnected()) {
+      LOGGER.error("Not connected to the LDAP server. Connection instance: {}", connection);
+      throw new IllegalStateException("The connection to the LDAP server is not alive");
+    }
+    LOGGER.info("Connected to LDAP.");
+  }
+
+
+  /**
+   * Extracts meaningful values from the search result.
+   *
+   * @param groupResponses          the result entries returned by the search
+   * @param ambariLdapConfiguration holds the keys of the meaningful attributes
+   * @return a set with the group names the test user belongs to
+   */
+  private Set<String> processGroupResults(Set<Response> groupResponses, AmbariLdapConfiguration ambariLdapConfiguration) {
+    Set<String> groupStrSet = Sets.newHashSet();
+    for (Response response : groupResponses) {
+      Entry entry = ((SearchResultEntryDecorator) response).getEntry();
+      groupStrSet.add(entry.get(ambariLdapConfiguration.groupNameAttribute()).get().getString());
+    }
+
+    LOGGER.debug("Extracted group names from group search responses: {}", groupStrSet);
+    return groupStrSet;
+  }
+
+  private void closeResources(LdapConnection connection, SearchCursor searchCursor) {
+    LOGGER.debug("Housekeeping: closing the connection and the search cursor ...");
+
+    if (null != searchCursor) {
+      // this method is idempotent
+      searchCursor.close();
+    }
+
+    if (null != connection) {
+      try {
+        connection.close();
+      } catch (IOException e) {
+        LOGGER.error("Exception occurred while closing the connection", e);
+      }
+    }
+  }
+
+}
+
+
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/c87043c9/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java
new file mode 100644
index 0000000..ced52fc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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.ldap.service.ads;
+
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.service.LdapConnectionService;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class DefaultLdapConnectionService implements LdapConnectionService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConnectionService.class);
+
+  @Override
+  public LdapNetworkConnection createLdapConnection(AmbariLdapConfiguration ambariLdapConfiguration) {
+    LOGGER.debug("Creating ldap connection instance from: {}", ambariLdapConfiguration);
+    return new LdapNetworkConnection(getLdapConnectionConfig(ambariLdapConfiguration));
+  }
+
+  private LdapConnectionConfig getLdapConnectionConfig(AmbariLdapConfiguration ambariAmbariLdapConfiguration) {
+    LOGGER.debug("Creating a configuration instance based on the ambari configuration: {}", ambariAmbariLdapConfiguration);
+
+    LdapConnectionConfig ldapConnectionConfig = new LdapConnectionConfig();
+    ldapConnectionConfig.setLdapHost(ambariAmbariLdapConfiguration.ldapServerHost());
+    ldapConnectionConfig.setLdapPort(ambariAmbariLdapConfiguration.ldapServerPort());
+    ldapConnectionConfig.setUseSsl(ambariAmbariLdapConfiguration.useSSL());
+
+    // todo set the other values as required
+    return ldapConnectionConfig;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c87043c9/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java
deleted file mode 100644
index 663ea12..0000000
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.ldap.service.ad;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.util.Map;
-
-import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
-import org.apache.ambari.server.ldap.service.LdapConnectionService;
-import org.apache.directory.api.ldap.model.cursor.EntryCursor;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.ldap.client.api.LdapConnection;
-import org.apache.directory.ldap.client.api.LdapConnectionConfig;
-import org.apache.directory.ldap.client.api.LdapNetworkConnection;
-import org.apache.directory.shared.ldap.constants.SchemaConstants;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
-
-public class DefaultLdapConfigurationValidatorServiceTest {
-  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class);
-  private static final String TEST_USER = "einstein";
-
-  LdapConfigurationValidatorService ldapConfigurationValidatorService = new DefaultLdapConfigurationValidatorService();
-
-
-  @Test
-  public void testCheckAttributes() throws Exception {
-
-    // WHEN
-    LdapConnectionConfig config = new LdapConnectionConfig();
-    config.setLdapHost("localhost");
-    config.setLdapPort(389);
-    LdapConnection connection = new LdapNetworkConnection(config);
-
-    // THEN
-    connection.anonymousBind();
-
-
-    EntryCursor cursor = connection.search("dc=dev,dc=local", "(objectclass=*)", SearchScope.ONELEVEL);
-
-    for (Entry entry : cursor) {
-      assertNotNull(entry);
-      System.out.println(entry);
-    }
-
-    cursor.close();
-
-  }
-
-  @Test
-  public void testCheckUserAttributes() throws Exception {
-    // GIVEN
-    Map<String, Object> ldapPropsMap = Maps.newHashMap();
-
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
-
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_SEARCH_BASE.propertyName(), "dc=example,dc=com");
-
-
-    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
-    LdapConnectionService connectionService = new DefaultLdapConnectionService();
-    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
-
-    ldapConfigurationValidatorService.checkUserAttributes(ldapConnection, "einstein", "", ambariLdapConfiguration);
-  }
-
-  @Test
-  public void testRetrieveGorupsForuser() throws Exception {
-    // GIVEN
-    Map<String, Object> ldapPropsMap = Maps.newHashMap();
-
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
-
-
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE.propertyName(), SchemaConstants.UNIQUE_MEMBER_AT);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_SEARCH_BASE.propertyName(), "dc=example,dc=com");
-
-
-    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
-    LdapConnectionService connectionService = new DefaultLdapConnectionService();
-    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
-
-    ldapConfigurationValidatorService.checkGroupAttributes(ldapConnection, "uid=einstein,dc=example,dc=com", ambariLdapConfiguration);
-  }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/c87043c9/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java
new file mode 100644
index 0000000..1c7f75d
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.ldap.service.ads;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.service.LdapConnectionService;
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class DefaultLdapConfigurationValidatorServiceTest {
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class);
+  private static final String TEST_USER = "einstein";
+
+  LdapConfigurationValidatorService ldapConfigurationValidatorService = new DefaultLdapConfigurationValidatorService();
+
+
+  @Test
+  public void testCheckAttributes() throws Exception {
+
+    // WHEN
+    LdapConnectionConfig config = new LdapConnectionConfig();
+    config.setLdapHost("localhost");
+    config.setLdapPort(389);
+    LdapConnection connection = new LdapNetworkConnection(config);
+
+    // THEN
+    connection.anonymousBind();
+
+
+    EntryCursor cursor = connection.search("dc=dev,dc=local", "(objectclass=*)", SearchScope.ONELEVEL);
+
+    for (Entry entry : cursor) {
+      assertNotNull(entry);
+      System.out.println(entry);
+    }
+
+    cursor.close();
+
+  }
+
+  @Test
+  public void testCheckUserAttributes() throws Exception {
+    // GIVEN
+    Map<String, Object> ldapPropsMap = Maps.newHashMap();
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_SEARCH_BASE.propertyName(), "dc=example,dc=com");
+
+
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
+    LdapConnectionService connectionService = new DefaultLdapConnectionService();
+    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
+
+    ldapConfigurationValidatorService.checkUserAttributes(ldapConnection, "einstein", "", ambariLdapConfiguration);
+  }
+
+  @Test
+  public void testRetrieveGorupsForuser() throws Exception {
+    // GIVEN
+    Map<String, Object> ldapPropsMap = Maps.newHashMap();
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
+
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE.propertyName(), SchemaConstants.UNIQUE_MEMBER_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_SEARCH_BASE.propertyName(), "dc=example,dc=com");
+
+
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
+    LdapConnectionService connectionService = new DefaultLdapConnectionService();
+    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
+
+    ldapConfigurationValidatorService.checkGroupAttributes(ldapConnection, "uid=einstein,dc=example,dc=com", ambariLdapConfiguration);
+  }
+}
\ No newline at end of file


[12/38] ambari git commit: AMBARI-21893 : NameNode Heap Usage (Daily) metric alert status flips to UNKNOWN intermittently when AMS HTTPS is enabled. (Addendum patch) (avijayan)

Posted by lp...@apache.org.
AMBARI-21893 : NameNode Heap Usage (Daily) metric alert status flips to UNKNOWN intermittently when AMS HTTPS is enabled. (Addendum patch) (avijayan)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4f6ef91f
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4f6ef91f
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4f6ef91f

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 4f6ef91f33cefeea97629dd4dc45ec993b27b4f6
Parents: a49121b
Author: Aravindan Vijayan <av...@hortonworks.com>
Authored: Tue Sep 12 19:54:01 2017 -0700
Committer: Aravindan Vijayan <av...@hortonworks.com>
Committed: Tue Sep 12 19:54:01 2017 -0700

----------------------------------------------------------------------
 .../AMBARI_METRICS/0.1.0/package/scripts/ams.py          | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/4f6ef91f/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/ams.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/ams.py b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/ams.py
index 51e0756..c72e2f0 100644
--- a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/ams.py
+++ b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/ams.py
@@ -515,12 +515,11 @@ def export_ca_certs(dir_path):
   truststore_p12 = os.path.join(tmpdir,'truststore.p12')
 
   if (params.metric_truststore_type.lower() == 'jks'):
-    if not params.metric_truststore_alias:
-      for alias in params.metric_truststore_alias_list:
-        # Convert truststore from JKS to PKCS12
-        cmd = format("{sudo} {java64_home}/bin/keytool -importkeystore -srckeystore {metric_truststore_path} -destkeystore {truststore_p12} -srcalias " + alias + " -deststoretype PKCS12 -srcstorepass {metric_truststore_password} -deststorepass {metric_truststore_password}")
-        Execute(cmd,
-        )
+    for alias in params.metric_truststore_alias_list:
+      # Convert truststore from JKS to PKCS12
+      cmd = format("{sudo} {java64_home}/bin/keytool -importkeystore -srckeystore {metric_truststore_path} -destkeystore {truststore_p12} -srcalias " + alias + " -deststoretype PKCS12 -srcstorepass {metric_truststore_password} -deststorepass {metric_truststore_password}")
+      Execute(cmd,
+              )
     truststore = truststore_p12
 
   # Export all CA certificates from the truststore to the conf directory


[07/38] ambari git commit: AMBARI-21936. Do not export YARN_CONF_DIR in "yarn-env.sh" file.(vbrodetskyi)

Posted by lp...@apache.org.
AMBARI-21936. Do not export YARN_CONF_DIR in "yarn-env.sh" file.(vbrodetskyi)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/aaf6f0ae
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/aaf6f0ae
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/aaf6f0ae

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: aaf6f0ae0f69ed80c1f8ec9ffaf81cf3a358900a
Parents: 321f9cf
Author: Vitaly Brodetskyi <vb...@hortonworks.com>
Authored: Tue Sep 12 20:31:56 2017 +0300
Committer: Vitaly Brodetskyi <vb...@hortonworks.com>
Committed: Tue Sep 12 20:31:56 2017 +0300

----------------------------------------------------------------------
 .../common-services/YARN/3.0.0.3.0/configuration/yarn-env.xml     | 3 ---
 1 file changed, 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf6f0ae/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/configuration/yarn-env.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/configuration/yarn-env.xml b/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/configuration/yarn-env.xml
index aaa72d1..4e722ee 100644
--- a/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/configuration/yarn-env.xml
+++ b/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/configuration/yarn-env.xml
@@ -179,9 +179,6 @@ fi
 # User for YARN daemons
 export HADOOP_YARN_USER=${HADOOP_YARN_USER:-yarn}
 
-# resolve links - $0 may be a softlink
-export YARN_CONF_DIR="${YARN_CONF_DIR:-$HADOOP_YARN_HOME/conf}"
-
 # some Java parameters
 # export JAVA_HOME=/home/y/libexec/jdk1.6.0/
 if [ "$JAVA_HOME" != "" ]; then


[31/38] ambari git commit: AMBARI-21307 LDAP config rest service implementation extends the ambari config rest implementaiton

Posted by lp...@apache.org.
AMBARI-21307 LDAP config rest  service implementation extends the ambari config rest implementaiton


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/e459461f
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/e459461f
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/e459461f

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: e459461f2c9fc7fe1600f3441d7eab870a278b0b
Parents: c87043c
Author: lpuskas <lp...@apache.org>
Authored: Mon Aug 21 15:53:45 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:31 2017 +0200

----------------------------------------------------------------------
 .../services/ldap/LdapConfigurationService.java | 208 +++++++++++++++++++
 .../api/services/ldap/LdapRestService.java      | 149 -------------
 2 files changed, 208 insertions(+), 149 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/e459461f/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
new file mode 100644
index 0000000..52244bc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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.ldap;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.ambari.annotations.ApiIgnore;
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.api.services.AmbariConfigurationService;
+import org.apache.ambari.server.api.services.Result;
+import org.apache.ambari.server.api.services.ResultImpl;
+import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.controller.internal.ResourceImpl;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationFactory;
+import org.apache.ambari.server.ldap.service.LdapFacade;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Endpoint designated to LDAP specific operations.
+ */
+@StaticallyInject
+@Path("/ldapconfigs/")
+public class LdapConfigurationService extends AmbariConfigurationService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(LdapConfigurationService.class);
+
+  @Inject
+  private static LdapFacade ldapFacade;
+
+  @Inject
+  private static LdapConfigurationFactory ldapConfigurationFactory;
+
+  /**
+   * Actions supported by this endpoint
+   */
+  private enum LdapAction {
+    TEST_CONNECTION("test-connection"),
+    TEST_ATTRIBUTES("test-attributes"),
+    DETECT_ATTRIBUTES("detect-attributes");
+
+    private String actionStr;
+
+    LdapAction(String actionStr) {
+      this.actionStr = actionStr;
+    }
+
+    public static LdapAction fromAction(String action) {
+      for (LdapAction val : LdapAction.values()) {
+        if (val.action().equals(action)) {
+          return val;
+        }
+      }
+      throw new IllegalStateException("Action [ " + action + " ] is not supported");
+    }
+
+    public String action() {
+      return this.actionStr;
+    }
+  }
+
+  @POST
+  @ApiIgnore // until documented
+  @Path("/validate")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response validateConfiguration(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
+
+    authorize();
+
+    Set<String> groups = Sets.newHashSet();
+
+    Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
+    try {
+
+      validateRequest(ldapCheckConfigurationRequest);
+
+      AmbariLdapConfiguration ambariLdapConfiguration = ldapConfigurationFactory.createLdapConfiguration(
+        ldapCheckConfigurationRequest.getAmbariConfiguration().getData().iterator().next());
+
+      LdapAction action = LdapAction.fromAction(ldapCheckConfigurationRequest.getRequestInfo().getAction());
+      switch (action) {
+
+        case TEST_CONNECTION:
+
+          LOGGER.info("Testing connection to the LDAP server ...");
+          ldapFacade.checkConnection(ambariLdapConfiguration);
+
+          break;
+        case TEST_ATTRIBUTES:
+
+          LOGGER.info("Testing LDAP attributes ....");
+          groups = ldapFacade.checkLdapAttibutes(ldapCheckConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
+          setResult(groups, result);
+
+          break;
+        case DETECT_ATTRIBUTES:
+
+          LOGGER.info("Detecting LDAP attributes ...");
+          ldapFacade.detectAttributes(ambariLdapConfiguration);
+
+          break;
+        default:
+          LOGGER.warn("No action provided ...");
+          throw new IllegalArgumentException("No request action provided");
+      }
+
+    } catch (Exception e) {
+      result.setResultStatus(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e));
+    }
+
+    return Response.status(result.getStatus().getStatusCode()).entity(getResultSerializer().serialize(result)).build();
+  }
+
+  private void setResult(Set<String> groups, Result result) {
+    Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
+    resource.setProperty("groups", groups);
+    result.getResultTree().addChild(resource, "payload");
+  }
+
+  private void validateRequest(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
+    String errMsg;
+
+    if (null == ldapCheckConfigurationRequest) {
+      errMsg = "No ldap configuraiton request provided";
+      LOGGER.error(errMsg);
+      throw new IllegalArgumentException(errMsg);
+    }
+
+    if (null == ldapCheckConfigurationRequest.getRequestInfo()) {
+      errMsg = String.format("No request information provided. Request: [%s]", ldapCheckConfigurationRequest);
+      LOGGER.error(errMsg);
+      throw new IllegalArgumentException(errMsg);
+    }
+
+    if (null == ldapCheckConfigurationRequest.getAmbariConfiguration()
+      || ldapCheckConfigurationRequest.getAmbariConfiguration().getData().size() != 1) {
+      errMsg = String.format("No / Invalid configuration data provided. Request: [%s]", ldapCheckConfigurationRequest);
+      LOGGER.error(errMsg);
+      throw new IllegalArgumentException(errMsg);
+    }
+  }
+
+  private void authorize() {
+    try {
+      Authentication authentication = AuthorizationHelper.getAuthentication();
+
+      if (authentication == null || !authentication.isAuthenticated()) {
+        throw new AuthorizationException("Authentication data is not available, authorization to perform the requested operation is not granted");
+      }
+
+      if (!AuthorizationHelper.isAuthorized(authentication, ResourceType.AMBARI, null, requiredAuthorizations())) {
+        throw new AuthorizationException("The authenticated user does not have the appropriate authorizations to create the requested resource(s)");
+      }
+    } catch (AuthorizationException e) {
+      LOGGER.error("Unauthorized operation.", e);
+      throw new IllegalArgumentException("User is not authorized to perform the operation", e);
+    }
+
+  }
+
+  Set<RoleAuthorization> requiredAuthorizations() {
+    return Sets.newHashSet(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/e459461f/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
deleted file mode 100644
index 4e654dc..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * 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.ldap;
-
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.ambari.annotations.ApiIgnore;
-import org.apache.ambari.server.StaticallyInject;
-import org.apache.ambari.server.api.services.BaseService;
-import org.apache.ambari.server.api.services.Result;
-import org.apache.ambari.server.api.services.ResultImpl;
-import org.apache.ambari.server.api.services.ResultStatus;
-import org.apache.ambari.server.controller.internal.ResourceImpl;
-import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.LdapConfigurationFactory;
-import org.apache.ambari.server.ldap.service.LdapFacade;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Sets;
-
-/**
- * Endpoint designated to LDAP specific operations.
- */
-@StaticallyInject
-@Path("/ldap")
-public class LdapRestService extends BaseService {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(LdapRestService.class);
-
-  @Inject
-  private static LdapFacade ldapFacade;
-
-  @Inject
-  private static LdapConfigurationFactory ldapConfigurationFactory;
-
-  @POST
-  @ApiIgnore // until documented
-  @Path("/validate") // todo this needs to be moved under the resource
-  @Consumes(MediaType.APPLICATION_JSON)
-  @Produces(MediaType.APPLICATION_JSON)
-  public Response validateConfiguration(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
-
-    Set<String> groups = Sets.newHashSet();
-
-    Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
-    try {
-
-      validateRequest(ldapCheckConfigurationRequest);
-
-      AmbariLdapConfiguration ambariLdapConfiguration = ldapConfigurationFactory.createLdapConfiguration(
-        ldapCheckConfigurationRequest.getAmbariConfiguration().getData().iterator().next());
-
-      switch (ldapCheckConfigurationRequest.getRequestInfo().getAction()) {
-        case "test-connection":
-
-          LOGGER.info("Testing connection to the LDAP server ...");
-          ldapFacade.checkConnection(ambariLdapConfiguration);
-
-          break;
-        case "test-attributes":
-
-          LOGGER.info("Testing LDAP attributes ....");
-          groups = ldapFacade.checkLdapAttibutes(ldapCheckConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
-          setResult(groups, result);
-
-          break;
-        case "detect-attributes":
-
-          LOGGER.info("Detecting LDAP attributes ...");
-          ldapFacade.detectAttributes(ambariLdapConfiguration);
-
-          break;
-        default:
-          LOGGER.warn("No action provided ...");
-          throw new IllegalArgumentException("No request action provided");
-      }
-
-    } catch (Exception e) {
-      result.setResultStatus(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e));
-    }
-
-    return Response.status(result.getStatus().getStatusCode()).entity(getResultSerializer().serialize(result)).build();
-  }
-
-  private void setResult(Set<String> groups, Result result) {
-    Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
-    resource.setProperty("groups", groups);
-    result.getResultTree().addChild(resource, "payload");
-  }
-
-  private void validateRequest(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
-    String errMsg;
-
-    if (null == ldapCheckConfigurationRequest) {
-      errMsg = "No ldap configuraiton request provided";
-      LOGGER.error(errMsg);
-      throw new IllegalArgumentException(errMsg);
-    }
-
-    if (null == ldapCheckConfigurationRequest.getRequestInfo()) {
-      errMsg = String.format("No request information provided. Request: [%s]", ldapCheckConfigurationRequest);
-      LOGGER.error(errMsg);
-      throw new IllegalArgumentException(errMsg);
-    }
-
-    if (null == ldapCheckConfigurationRequest.getAmbariConfiguration()
-      || ldapCheckConfigurationRequest.getAmbariConfiguration().getData().size() != 1) {
-      errMsg = String.format("No / Invalid configuration data provided. Request: [%s]", ldapCheckConfigurationRequest);
-      LOGGER.error(errMsg);
-      throw new IllegalArgumentException(errMsg);
-    }
-  }
-}


[06/38] ambari git commit: AMBARI-21931 - Use Correct Packages For Clients Where Stack Tools Support It (jonathanhurley)

Posted by lp...@apache.org.
AMBARI-21931 - Use Correct Packages For Clients Where Stack Tools Support It (jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/321f9cfe
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/321f9cfe
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/321f9cfe

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 321f9cfeb42006ce309d09dbd7af1e6601c90ba5
Parents: 5113e99
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Mon Sep 11 15:41:22 2017 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Tue Sep 12 12:29:31 2017 -0400

----------------------------------------------------------------------
 .../libraries/functions/stack_select.py         | 65 ++++++++++++++++++-
 .../ambari/server/topology/AmbariContext.java   |  2 +-
 .../HDP/2.0.6/properties/stack_packages.json    | 66 +++++++++++++------
 .../HDP/3.0/properties/stack_packages.json      | 48 ++++++++------
 .../src/test/python/TestStackSelect.py          | 67 ++++++++++++++++++--
 .../src/test/python/stacks/utils/RMFTestCase.py | 30 +++++----
 6 files changed, 222 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/321f9cfe/ambari-common/src/main/python/resource_management/libraries/functions/stack_select.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/libraries/functions/stack_select.py b/ambari-common/src/main/python/resource_management/libraries/functions/stack_select.py
index 1657c23..e506974 100644
--- a/ambari-common/src/main/python/resource_management/libraries/functions/stack_select.py
+++ b/ambari-common/src/main/python/resource_management/libraries/functions/stack_select.py
@@ -33,6 +33,7 @@ from resource_management.libraries.functions.get_stack_version import get_stack_
 from resource_management.libraries.functions.format import format
 from resource_management.libraries.script.script import Script
 from resource_management.libraries.functions import stack_tools
+from resource_management.core import shell
 from resource_management.core.shell import call
 from resource_management.libraries.functions.version import format_stack_version
 from resource_management.libraries.functions.version_select_util import get_versions_from_stack_root
@@ -75,6 +76,11 @@ PACKAGE_SCOPE_INSTALL = "INSTALL"
 PACKAGE_SCOPE_STANDARD = "STANDARD"
 PACKAGE_SCOPE_PATCH = "PATCH"
 PACKAGE_SCOPE_STACK_SELECT = "STACK-SELECT-PACKAGE"
+
+# the legacy key is used when a package has changed from one version of the stack select tool to another.
+_PACKAGE_SCOPE_LEGACY = "LEGACY"
+
+# the valid scopes which can be requested
 _PACKAGE_SCOPES = (PACKAGE_SCOPE_INSTALL, PACKAGE_SCOPE_STANDARD, PACKAGE_SCOPE_PATCH, PACKAGE_SCOPE_STACK_SELECT)
 
 # the orchestration types which equal to a partial (non-STANDARD) upgrade
@@ -110,6 +116,37 @@ def get_package_name(default_package = None):
       raise
 
 
+def is_package_supported(package, supported_packages = None):
+  """
+  Gets whether the specified package is supported by the <stack_select> tool.
+  :param package: the package to check
+  :param supported_packages: the list of supported packages pre-fetched
+  :return: True if the package is support, False otherwise
+  """
+  if supported_packages is None:
+    supported_packages = get_supported_packages()
+
+  if package in supported_packages:
+    return True
+
+  return False
+
+
+def get_supported_packages():
+  """
+  Parses the output from <stack-select> packages and returns an array of the various packages.
+  :return: and array of packages support by <stack-select>
+  """
+  stack_selector_path = stack_tools.get_stack_tool_path(stack_tools.STACK_SELECTOR_NAME)
+  command = (STACK_SELECT_PREFIX, stack_selector_path, "packages")
+  code, stdout = shell.call(command, sudo = True,  quiet = True)
+
+  if code != 0 or stdout is None:
+    raise Fail("Unable to query for supported packages using {0}".format(stack_selector_path))
+
+  # turn the output into lines, stripping each line
+  return [line.strip() for line in stdout.splitlines()]
+
 
 def get_packages(scope, service_name = None, component_name = None):
   """
@@ -172,7 +209,33 @@ def get_packages(scope, service_name = None, component_name = None):
     Logger.info("Skipping stack-select on {0} because it does not exist in the stack-select package structure.".format(component_name))
     return None
 
-  return data[component_name][scope]
+  # this one scope is not an array, so transform it into one for now so we can
+  # use the same code below
+  packages = data[component_name][scope]
+  if scope == PACKAGE_SCOPE_STACK_SELECT:
+    packages = [packages]
+
+  # grab the package name from the JSON and validate it against the packages
+  # that the stack-select tool supports - if it doesn't support it, then try to find the legacy
+  # package name if it exists
+  supported_packages = get_supported_packages()
+  for index, package in enumerate(packages):
+    if not is_package_supported(package, supported_packages=supported_packages):
+      if _PACKAGE_SCOPE_LEGACY in data[component_name]:
+        legacy_package = data[component_name][_PACKAGE_SCOPE_LEGACY]
+        Logger.info(
+          "The package {0} is not supported by this version of the stack-select tool, defaulting to the legacy package of {1}".format(package, legacy_package))
+
+        # use the legacy package
+        packages[index] = legacy_package
+      else:
+        raise Fail("The package {0} is not supported by this version of the stack-select tool.".format(package))
+
+  # transform the array bcak to a single element
+  if scope == PACKAGE_SCOPE_STACK_SELECT:
+    packages = packages[0]
+
+  return packages
 
 
 def select_all(version_to_select):

http://git-wip-us.apache.org/repos/asf/ambari/blob/321f9cfe/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
index 1556b0d..eb39562 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
@@ -206,7 +206,7 @@ public class AmbariContext {
     StackId stackId = new StackId(stack.getName(), stack.getVersion());
 
     RepositoryVersionEntity repoVersion = null;
-    if (null == repoVersionString && null == repoVersionId) {
+    if (StringUtils.isEmpty(repoVersionString) && null == repoVersionId) {
       List<RepositoryVersionEntity> stackRepoVersions = repositoryVersionDAO.findByStack(stackId);
 
       if (stackRepoVersions.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/321f9cfe/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json b/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
index 704fb54..ec35f2b 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
@@ -298,12 +298,13 @@
           ]
         },
         "HDFS_CLIENT": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "hadoop-hdfs-client",
+          "LEGACY": "hadoop-client",
           "INSTALL": [
-            "hadoop-client"
+            "hadoop-hdfs-client"
           ],
           "PATCH": [
-            "INVALID"
+            "hadoop-hdfs-client"
           ],
           "STANDARD": [
             "hadoop-client"
@@ -420,12 +421,13 @@
           ]
         },
         "HIVE_CLIENT": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "hive-client",
+          "LEGACY": "hadoop-client",
           "INSTALL": [
-            "hadoop-client"
+            "hive-client"
           ],
           "PATCH": [
-            "INVALID"
+            "hive-client"
           ],
           "STANDARD": [
             "hadoop-client"
@@ -500,12 +502,13 @@
           ]
         },
         "MAPREDUCE2_CLIENT": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "hadoop-mapreduce-client",
+          "LEGACY": "hadoop-client",
           "INSTALL": [
-            "hadoop-client"
+            "hadoop-mapreduce-client"
           ],
           "PATCH": [
-            "hadoop-mapreduce-INVALID"
+            "hadoop-mapreduce-client"
           ],
           "STANDARD": [
             "hadoop-client"
@@ -542,12 +545,13 @@
       },
       "PIG": {
         "PIG": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "pig-client",
+          "LEGACY": "hadoop-client",
           "INSTALL": [
-            "hadoop-client"
+            "pig-client"
           ],
           "PATCH": [
-            "INVALID"
+            "pig-client"
           ],
           "STANDARD": [
             "hadoop-client"
@@ -636,6 +640,18 @@
         }
       },
       "SPARK": {
+        "LIVY_CLIENT": {
+          "STACK-SELECT-PACKAGE": "livy-client",
+          "INSTALL": [
+            "livy-client"
+          ],
+          "PATCH": [
+            "livy-client"
+          ],
+          "STANDARD": [
+            "livy-client"
+          ]
+        },
         "LIVY_SERVER": {
           "STACK-SELECT-PACKAGE": "livy-server",
           "INSTALL": [
@@ -686,6 +702,18 @@
         }
       },
       "SPARK2": {
+        "LIVY2_CLIENT": {
+          "STACK-SELECT-PACKAGE": "livy2-client",
+          "INSTALL": [
+            "livy2-client"
+          ],
+          "PATCH": [
+            "livy2-client"
+          ],
+          "STANDARD": [
+            "livy2-client"
+          ]
+        },
         "LIVY2_SERVER": {
           "STACK-SELECT-PACKAGE": "livy2-server",
           "INSTALL": [
@@ -819,12 +847,13 @@
       },
       "TEZ": {
         "TEZ_CLIENT": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "tez-client",
+          "LEGACY": "hadoop-client",
           "INSTALL": [
-            "hadoop-client"
+            "tez-client"
           ],
           "PATCH": [
-            "INVALID"
+            "tez-client"
           ],
           "STANDARD": [
             "hadoop-client"
@@ -895,12 +924,13 @@
           ]
         },
         "YARN_CLIENT": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "hadoop-yarn-client",
+          "LEGACY": "hadoop-client",
           "INSTALL": [
-            "hadoop-client"
+            "hadoop-yarn-client"
           ],
           "PATCH": [
-            "INVALID"
+            "hadoop-yarn-client"
           ],
           "STANDARD": [
             "hadoop-client"

http://git-wip-us.apache.org/repos/asf/ambari/blob/321f9cfe/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json b/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
index 0ef41a6..9012e92 100644
--- a/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
+++ b/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
@@ -298,12 +298,12 @@
           ]
         },
         "HDFS_CLIENT": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "hadoop-hdfs-client",
           "INSTALL": [
-            "hadoop-client"
+            "hadoop-hdfs-client"
           ],
           "PATCH": [
-            "INVALID"
+            "hadoop-hdfs-client"
           ],
           "STANDARD": [
             "hadoop-client"
@@ -420,12 +420,12 @@
           ]
         },
         "HIVE_CLIENT": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "hive-client",
           "INSTALL": [
-            "hadoop-client"
+            "hive-client"
           ],
           "PATCH": [
-            "INVALID"
+            "hive-client"
           ],
           "STANDARD": [
             "hadoop-client"
@@ -500,12 +500,12 @@
           ]
         },
         "MAPREDUCE2_CLIENT": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "hadoop-mapreduce-client",
           "INSTALL": [
-            "hadoop-client"
+            "hadoop-mapreduce-client"
           ],
           "PATCH": [
-            "hadoop-mapreduce-INVALID"
+            "hadoop-mapreduce-client"
           ],
           "STANDARD": [
             "hadoop-client"
@@ -542,12 +542,12 @@
       },
       "PIG": {
         "PIG": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "pig-client",
           "INSTALL": [
-            "hadoop-client"
+            "pig-client"
           ],
           "PATCH": [
-            "INVALID"
+            "pig-client"
           ],
           "STANDARD": [
             "hadoop-client"
@@ -622,6 +622,18 @@
         }
       },
       "SPARK": {
+        "LIVY_CLIENT": {
+          "STACK-SELECT-PACKAGE": "livy2-client",
+          "INSTALL": [
+            "livy2-client"
+          ],
+          "PATCH": [
+            "livy2-client"
+          ],
+          "STANDARD": [
+            "livy2-client"
+          ]
+        },
         "LIVY_SERVER": {
           "STACK-SELECT-PACKAGE": "livy2-server",
           "INSTALL": [
@@ -741,12 +753,12 @@
       },
       "TEZ": {
         "TEZ_CLIENT": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "tez-client",
           "INSTALL": [
-            "hadoop-client"
+            "tez-client"
           ],
           "PATCH": [
-            "INVALID"
+            "tez-client"
           ],
           "STANDARD": [
             "hadoop-client"
@@ -791,12 +803,12 @@
           ]
         },
         "YARN_CLIENT": {
-          "STACK-SELECT-PACKAGE": "hadoop-client",
+          "STACK-SELECT-PACKAGE": "hadoop-yarn-client",
           "INSTALL": [
-            "hadoop-client"
+            "hadoop-yarn-client"
           ],
           "PATCH": [
-            "INVALID"
+            "hadoop-yarn-client"
           ],
           "STANDARD": [
             "hadoop-client"

http://git-wip-us.apache.org/repos/asf/ambari/blob/321f9cfe/ambari-server/src/test/python/TestStackSelect.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/TestStackSelect.py b/ambari-server/src/test/python/TestStackSelect.py
index 3d4e5b6..8cd8f2f 100644
--- a/ambari-server/src/test/python/TestStackSelect.py
+++ b/ambari-server/src/test/python/TestStackSelect.py
@@ -19,6 +19,7 @@ limitations under the License.
 '''
 
 from mock.mock import patch
+from mock.mock import MagicMock
 
 from resource_management.core.logger import Logger
 from resource_management.core.exceptions import Fail
@@ -43,13 +44,15 @@ class TestStackSelect(TestCase):
 
     self.assertRaises(Fail, stack_select.select_packages, version)
 
-
+  @patch.object(stack_select, "get_supported_packages")
   @patch("resource_management.libraries.functions.stack_select.select")
-  def test_select_package_for_standard_orchestration(self, stack_select_select_mock):
+  def test_select_package_for_standard_orchestration(self, stack_select_select_mock, get_supported_packages_mock):
     """
     Tests that missing the service & role throws an excpetion
     :return:
     """
+    get_supported_packages_mock.return_value = TestStackSelect._get_supported_packages()
+
     version = "2.5.9.9-9999"
 
     command_json = TestStackSelect._get_cluster_simple_upgrade_json()
@@ -66,13 +69,15 @@ class TestStackSelect(TestCase):
     self.assertEqual(stack_select_select_mock.call_args_list[0][0], ("foo-master", version))
     self.assertEqual(stack_select_select_mock.call_args_list[1][0], ("foo-client", version))
 
-
+  @patch.object(stack_select, "get_supported_packages")
   @patch("resource_management.libraries.functions.stack_select.select")
-  def test_select_package_for_patch_orchestration(self, stack_select_select_mock):
+  def test_select_package_for_patch_orchestration(self, stack_select_select_mock, get_supported_packages_mock):
     """
     Tests that missing the service & role throws an excpetion
     :return:
     """
+    get_supported_packages_mock.return_value = TestStackSelect._get_supported_packages()
+
     version = "2.5.9.9-9999"
 
     command_json = TestStackSelect._get_cluster_simple_upgrade_json()
@@ -98,6 +103,31 @@ class TestStackSelect(TestCase):
     self.assertEqual(stack_select_select_mock.call_args_list[0][0], ("foo-master", version))
 
 
+  @patch.object(stack_select, "get_supported_packages")
+  @patch("resource_management.libraries.functions.stack_select.select")
+  def test_legacy_package_fallback(self, stack_select_select_mock, get_supported_packages_mock):
+    """
+    Tests that if the package specified by the JSON isn't support by the stack-select tool,
+    the the fallback legacy value is used.
+    :return:
+    """
+    get_supported_packages_mock.return_value = ["foo-legacy"]
+
+    version = "2.5.9.9-9999"
+
+    command_json = TestStackSelect._get_cluster_simple_upgrade_json()
+
+    Script.config = dict()
+    Script.config.update(command_json)
+    Script.config.update( { "configurations" : { "cluster-env" : {} }, "hostLevelParams": {} } )
+    Script.config["configurations"]["cluster-env"]["stack_packages"] = self._get_stack_packages_with_legacy()
+    Script.config["hostLevelParams"] = { "stack_name" : "HDP" }
+
+    stack_select.select_packages(version)
+
+    self.assertEqual(len(stack_select_select_mock.call_args_list), 1)
+    self.assertEqual(stack_select_select_mock.call_args_list[0][0], ("foo-legacy", version))
+
   @staticmethod
   def _get_incomplete_cluster_simple_upgrade_json():
     """
@@ -197,3 +227,32 @@ class TestStackSelect(TestCase):
         }
       }
     } )
+
+  @staticmethod
+  def _get_stack_packages_with_legacy():
+    import json
+    return json.dumps( {
+      "HDP": {
+        "stack-select": {
+          "FOO_SERVICE": {
+            "FOO_MASTER": {
+              "LEGACY":"foo-legacy",
+              "STACK-SELECT-PACKAGE": "foo-master",
+              "INSTALL": [
+                "foo-master"
+              ],
+              "PATCH": [
+                "foo-master"
+              ],
+              "STANDARD": [
+                "foo-master"
+              ]
+            }
+          }
+        }
+      }
+    } )
+
+  @staticmethod
+  def _get_supported_packages():
+    return ["foo-master", "foo-client"]

http://git-wip-us.apache.org/repos/asf/ambari/blob/321f9cfe/ambari-server/src/test/python/stacks/utils/RMFTestCase.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/utils/RMFTestCase.py b/ambari-server/src/test/python/stacks/utils/RMFTestCase.py
index 6a0afa2..291f22b 100644
--- a/ambari-server/src/test/python/stacks/utils/RMFTestCase.py
+++ b/ambari-server/src/test/python/stacks/utils/RMFTestCase.py
@@ -139,20 +139,22 @@ class RMFTestCase(TestCase):
     if 'status_params' in sys.modules:
       del(sys.modules["status_params"])
 
-    with Environment(basedir, test_mode=True) as RMFTestCase.env:
-      with patch('resource_management.core.shell.checked_call', side_effect=checked_call_mocks) as mocks_dict['checked_call']:
-        with patch('resource_management.core.shell.call', side_effect=call_mocks) as mocks_dict['call']:
-          with patch.object(Script, 'get_config', return_value=self.config_dict) as mocks_dict['get_config']: # mocking configurations
-            with patch.object(Script, 'get_tmp_dir', return_value="/tmp") as mocks_dict['get_tmp_dir']:
-              with patch.object(Script, 'post_start') as mocks_dict['post_start']:
-                with patch('resource_management.libraries.functions.get_kinit_path', return_value=kinit_path_local) as mocks_dict['get_kinit_path']:
-                  with patch.object(platform, 'linux_distribution', return_value=os_type) as mocks_dict['linux_distribution']:
-                    with patch.object(os, "environ", new=os_env) as mocks_dict['environ']:
-                      if not try_install:
-                        with patch.object(Script, 'install_packages') as install_mock_value:
-                          method(RMFTestCase.env, *command_args)
-                      else:
-                        method(RMFTestCase.env, *command_args)
+    with Environment(basedir, test_mode=True) as RMFTestCase.env,\
+        patch('resource_management.core.shell.checked_call', side_effect=checked_call_mocks) as mocks_dict['checked_call'],\
+        patch('resource_management.core.shell.call', side_effect=call_mocks) as mocks_dict['call'],\
+        patch.object(Script, 'get_config', return_value=self.config_dict) as mocks_dict['get_config'],\
+        patch.object(Script, 'get_tmp_dir', return_value="/tmp") as mocks_dict['get_tmp_dir'],\
+        patch.object(Script, 'post_start') as mocks_dict['post_start'],\
+        patch('resource_management.libraries.functions.get_kinit_path', return_value=kinit_path_local) as mocks_dict['get_kinit_path'],\
+        patch.object(platform, 'linux_distribution', return_value=os_type) as mocks_dict['linux_distribution'],\
+        patch('resource_management.libraries.functions.stack_select.is_package_supported', return_value=True),\
+        patch('resource_management.libraries.functions.stack_select.get_supported_packages', return_value=MagicMock()),\
+        patch.object(os, "environ", new=os_env) as mocks_dict['environ']:
+      if not try_install:
+        with patch.object(Script, 'install_packages') as install_mock_value:
+          method(RMFTestCase.env, *command_args)
+      else:
+        method(RMFTestCase.env, *command_args)
 
     sys.path.remove(scriptsdir)
 


[02/38] ambari git commit: AMBARI-21928 In case if component package doesn't advertise his version, Ambari silently failing on deploy stack steps (dgrinenko)

Posted by lp...@apache.org.
AMBARI-21928 In case if component package doesn't advertise his version, Ambari silently failing on deploy stack steps (dgrinenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/001f290b
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/001f290b
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/001f290b

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 001f290be2622375786f27cc054727adb7be8905
Parents: 252e989
Author: Dmytro Grinenko <ha...@apache.org>
Authored: Tue Sep 12 15:12:44 2017 +0300
Committer: Dmytro Grinenko <ha...@apache.org>
Committed: Tue Sep 12 15:12:44 2017 +0300

----------------------------------------------------------------------
 .../libraries/functions/stack_tools.py          | 12 ++---
 .../libraries/functions/version_select_util.py  | 57 +++++++++-----------
 .../libraries/script/script.py                  |  2 +
 .../scripts/shared_initialization.py            | 19 +++----
 .../hooks/after-INSTALL/test_after_install.py   |  2 +-
 5 files changed, 42 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/001f290b/ambari-common/src/main/python/resource_management/libraries/functions/stack_tools.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/libraries/functions/stack_tools.py b/ambari-common/src/main/python/resource_management/libraries/functions/stack_tools.py
index fa97fd1..d9233a3 100644
--- a/ambari-common/src/main/python/resource_management/libraries/functions/stack_tools.py
+++ b/ambari-common/src/main/python/resource_management/libraries/functions/stack_tools.py
@@ -32,6 +32,7 @@ from resource_management.core.utils import pad
 STACK_SELECTOR_NAME = "stack_selector"
 CONF_SELECTOR_NAME = "conf_selector"
 
+
 def get_stack_tool(name):
   """
   Give a tool selector name get the stack-specific tool name, tool path, tool package
@@ -43,7 +44,7 @@ def get_stack_tool(name):
   stack_name = default("/hostLevelParams/stack_name", None)
   if stack_name is None:
     Logger.warning("Cannot find the stack name in the command. Stack tools cannot be loaded")
-    return (None, None, None)
+    return None, None, None
 
   stack_tools = None
   stack_tools_config = default("/configurations/cluster-env/stack_tools", None)
@@ -52,23 +53,22 @@ def get_stack_tool(name):
 
   if stack_tools is None:
     Logger.warning("The stack tools could not be found in cluster-env")
-    return (None, None, None)
+    return None, None, None
 
   if stack_name not in stack_tools:
     Logger.warning("Cannot find stack tools for the stack named {0}".format(stack_name))
-    return (None, None, None)
+    return None, None, None
 
   # load the stack tooks keyed by the stack name
   stack_tools = stack_tools[stack_name]
 
   if not stack_tools or not name or name.lower() not in stack_tools:
     Logger.warning("Cannot find config for {0} stack tool in {1}".format(str(name), str(stack_tools)))
-    return (None, None, None)
-
+    return None, None, None
 
   tool_config = stack_tools[name.lower()]
 
-  # Return fixed length (tool_name, tool_path tool_package) tuple
+  # Return fixed length (tool_name, tool_path, tool_package) tuple
   return tuple(pad(tool_config[:3], 3))
 
 def get_stack_tool_name(name):

http://git-wip-us.apache.org/repos/asf/ambari/blob/001f290b/ambari-common/src/main/python/resource_management/libraries/functions/version_select_util.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/libraries/functions/version_select_util.py b/ambari-common/src/main/python/resource_management/libraries/functions/version_select_util.py
index 79dc874..9fbb42b 100644
--- a/ambari-common/src/main/python/resource_management/libraries/functions/version_select_util.py
+++ b/ambari-common/src/main/python/resource_management/libraries/functions/version_select_util.py
@@ -26,7 +26,6 @@ import tempfile
 from resource_management.core.logger import Logger
 from resource_management.core import shell
 from resource_management.libraries.functions import stack_tools
-import ambari_simplejson as json # simplejson is much faster comparing to Python 2.6 json module and has the same functions set.
 
 
 def get_component_version(stack_name, component_name):
@@ -39,42 +38,36 @@ def get_component_version(stack_name, component_name):
   :return: Returns a string if found, e.g., 2.2.1.0-2175, otherwise, returns None
   """
   version = None
-  if stack_name is None or component_name is None:
+  if not stack_name or not component_name:
     Logger.error("Could not determine component version because of the parameters is empty. " \
                  "stack_name: %s, component_name: %s" % (str(stack_name), str(component_name)))
     return version
 
-  out = None
-  code = -1
-  if not stack_name:
-    Logger.error("Stack name not provided")
-  elif not component_name:
-    Logger.error("Component name not provided")
+  stack_selector_name, stack_selector_path, stack_selector_package = stack_tools.get_stack_tool(stack_tools.STACK_SELECTOR_NAME)
+  if stack_selector_name and stack_selector_path and os.path.exists(stack_selector_path):
+    tmpfile = tempfile.NamedTemporaryFile(delete=True)
+    out, code = None, -1
+    get_stack_comp_version_cmd = '%s status %s > %s' % (stack_selector_path, component_name, tmpfile.name)
+
+    try:
+      # This is necessary because Ubuntu returns "stdin: is not a tty", see AMBARI-8088
+      # ToDo: original problem looks strange
+      with open(tmpfile.name, 'r') as f:
+        code = shell.call(get_stack_comp_version_cmd, quiet=True)[0]
+        out = f.read()
+
+      if code != 0 or out is None:
+        raise ValueError("Code is nonzero or output is empty")
+
+      Logger.debug("Command: %s\nOutput: %s" % (get_stack_comp_version_cmd, str(out)))
+      matches = re.findall(r"( [\d\.]+(\-\d+)?)", out)
+      version = matches[0][0].strip() if matches and len(matches) > 0 and len(matches[0]) > 0 else None
+      Logger.debug("Version for component %s: %s" % (component_name, str(version)))
+    except Exception, e:
+      Logger.error("Could not determine stack version for component %s by calling '%s'. Return Code: %s, Output: %s." %
+                   (component_name, get_stack_comp_version_cmd, str(code), str(out)))
   else:
-    (stack_selector_name, stack_selector_path, stack_selector_package) = stack_tools.get_stack_tool(stack_tools.STACK_SELECTOR_NAME)
-    if stack_selector_name and stack_selector_path and os.path.exists(stack_selector_path):
-      tmpfile = tempfile.NamedTemporaryFile()
-
-      get_stack_comp_version_cmd = ""
-      try:
-        # This is necessary because Ubuntu returns "stdin: is not a tty", see AMBARI-8088
-        with open(tmpfile.name, 'r') as file:
-          get_stack_comp_version_cmd = '%s status %s > %s' % (stack_selector_path, component_name, tmpfile.name)
-          code, stdoutdata = shell.call(get_stack_comp_version_cmd, quiet=True)
-          out = file.read()
-
-        if code != 0 or out is None:
-          raise Exception("Code is nonzero or output is empty")
-
-        Logger.debug("Command: %s\nOutput: %s" % (get_stack_comp_version_cmd, str(out)))
-        matches = re.findall(r"( [\d\.]+(\-\d+)?)", out)
-        version = matches[0][0].strip() if matches and len(matches) > 0 and len(matches[0]) > 0 else None
-        Logger.debug("Version for component %s: %s" % (component_name, str(version)))
-      except Exception, e:
-        Logger.error("Could not determine stack version for component %s by calling '%s'. Return Code: %s, Output: %s." %
-                     (component_name, get_stack_comp_version_cmd, str(code), str(out)))
-    else:
-      Logger.error("Could not find stack selector for stack: %s" % str(stack_name))
+    Logger.error("Could not find stack selector for stack: %s" % str(stack_name))
 
   return version
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/001f290b/ambari-common/src/main/python/resource_management/libraries/script/script.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/libraries/script/script.py b/ambari-common/src/main/python/resource_management/libraries/script/script.py
index fcfac2b..0e352d1 100644
--- a/ambari-common/src/main/python/resource_management/libraries/script/script.py
+++ b/ambari-common/src/main/python/resource_management/libraries/script/script.py
@@ -228,6 +228,8 @@ class Script(object):
         repo_version_id = default("/hostLevelParams/repository_version_id", None)
         if repo_version_id:
           self.put_structured_out({"repository_version_id": repo_version_id})
+      else:
+        Logger.error("Component '{0}' did not advertise a version. This may indicate a problem with the component packaging.".format(stack_select_package_name))
 
 
   def should_expose_component_version(self, command_name):

http://git-wip-us.apache.org/repos/asf/ambari/blob/001f290b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/after-INSTALL/scripts/shared_initialization.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/after-INSTALL/scripts/shared_initialization.py b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/after-INSTALL/scripts/shared_initialization.py
index daaffd8..67c3ba8 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/after-INSTALL/scripts/shared_initialization.py
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/after-INSTALL/scripts/shared_initialization.py
@@ -46,7 +46,7 @@ def setup_stack_symlinks(struct_out_file):
     return
 
   if params.host_sys_prepped:
-    Logger.warning("Skipping running stack-selector-tool becase this is a sys_prepped host. This may cause symlink pointers not to be created for HDP componets installed later on top of an already sys_prepped host.")
+    Logger.warning("Skipping running stack-selector-tool because this is a sys_prepped host. This may cause symlink pointers not to be created for HDP components installed later on top of an already sys_prepped host")
     return
 
   # get the packages which the stack-select tool should be used on
@@ -105,17 +105,14 @@ def load_version(struct_out_file):
   """
   Load version from file.  Made a separate method for testing
   """
-  json_version = None
   try:
-    if os.path.exists(struct_out_file):
-      with open(struct_out_file, 'r') as fp:
-        json_info = json.load(fp)
-        json_version = json_info['version']
-  except:
-    pass
-
-  return json_version
-  
+    with open(struct_out_file, 'r') as fp:
+      json_info = json.load(fp)
+
+    return json_info['version']
+  except (IOError, KeyError, TypeError):
+    return None
+
 
 def link_configs(struct_out_file):
   """

http://git-wip-us.apache.org/repos/asf/ambari/blob/001f290b/ambari-server/src/test/python/stacks/2.0.6/hooks/after-INSTALL/test_after_install.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.0.6/hooks/after-INSTALL/test_after_install.py b/ambari-server/src/test/python/stacks/2.0.6/hooks/after-INSTALL/test_after_install.py
index d6740cb..f905cf9 100644
--- a/ambari-server/src/test/python/stacks/2.0.6/hooks/after-INSTALL/test_after_install.py
+++ b/ambari-server/src/test/python/stacks/2.0.6/hooks/after-INSTALL/test_after_install.py
@@ -344,4 +344,4 @@ class TestHookAfterInstall(RMFTestCase):
                        config_dict = json_content,
                        config_overrides = self.CONFIG_OVERRIDES)
 
-    logger_warning_mock.assert_any_call('Skipping running stack-selector-tool becase this is a sys_prepped host. This may cause symlink pointers not to be created for HDP componets installed later on top of an already sys_prepped host.')
+    logger_warning_mock.assert_any_call('Skipping running stack-selector-tool because this is a sys_prepped host. This may cause symlink pointers not to be created for HDP components installed later on top of an already sys_prepped host')


[32/38] ambari git commit: AMBARI-21307 refactoring - renamed, moved classes, variables

Posted by lp...@apache.org.
AMBARI-21307 refactoring - renamed, moved classes, variables


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/fa7d7ec3
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/fa7d7ec3
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/fa7d7ec3

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: fa7d7ec34b676fe2a2f9158fba1076f32f60baa9
Parents: e459461
Author: lpuskas <lp...@apache.org>
Authored: Tue Aug 22 10:03:24 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:31 2017 +0200

----------------------------------------------------------------------
 .../api/services/ldap/AmbariConfiguration.java  |  87 +++++++
 .../services/ldap/AmbariConfigurationDTO.java   |  67 -----
 .../ldap/LdapCheckConfigurationRequest.java     |  47 ----
 .../api/services/ldap/LdapConfigOperation.java  |  43 ++++
 .../services/ldap/LdapConfigurationRequest.java |  49 ++++
 .../services/ldap/LdapConfigurationService.java |  53 +---
 .../api/services/ldap/LdapOperationRequest.java |  18 --
 .../server/ldap/LdapConfigurationService.java   |  60 +++++
 .../ldap/LdapConfigurationValidatorService.java |  60 -----
 .../apache/ambari/server/ldap/LdapModule.java   |   4 +-
 .../server/ldap/service/AmbariLdapFacade.java   |  10 +-
 .../ads/DefaultLdapConfigurationService.java    | 243 +++++++++++++++++++
 ...efaultLdapConfigurationValidatorService.java | 243 -------------------
 .../api/services/ldap/LDAPServiceTest.java      |   6 +-
 .../DefaultLdapConfigurationServiceTest.java    | 113 +++++++++
 ...ltLdapConfigurationValidatorServiceTest.java | 113 ---------
 16 files changed, 618 insertions(+), 598 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
new file mode 100644
index 0000000..b5cc921
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
@@ -0,0 +1,87 @@
+/*
+ * 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.ldap;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Domain POJO representing generic ambari configuration data.
+ */
+public class AmbariConfiguration {
+
+  /**
+   * The type of the configuration,  eg.: ldap-configuration
+   */
+  private String type;
+
+  /**
+   * Version tag
+   */
+  private String versionTag;
+
+  /**
+   * Version number
+   */
+  private Integer version;
+
+  /**
+   * Created timestamp
+   */
+  private long createdTs;
+
+  private Set<Map<String, Object>> data = Collections.emptySet();
+
+  public String getType() {
+    return type;
+  }
+
+  public void setType(String type) {
+    this.type = type;
+  }
+
+  public Set<Map<String, Object>> getData() {
+    return data;
+  }
+
+  public void setData(Set<Map<String, Object>> data) {
+    this.data = data;
+  }
+
+  public String getVersionTag() {
+    return versionTag;
+  }
+
+  public void setVersionTag(String versionTag) {
+    this.versionTag = versionTag;
+  }
+
+  public Integer getVersion() {
+    return version;
+  }
+
+  public void setVersion(Integer version) {
+    this.version = version;
+  }
+
+  public long getCreatedTs() {
+    return createdTs;
+  }
+
+  public void setCreatedTs(long createdTs) {
+    this.createdTs = createdTs;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java
deleted file mode 100644
index 1b134fe..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.ldap;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-public class AmbariConfigurationDTO {
-  private String type;
-  private Set<Map<String, Object>> data = Collections.emptySet();
-  private String versionTag;
-  private Integer version;
-  private long createdTs;
-
-  public String getType() {
-    return type;
-  }
-
-  public void setType(String type) {
-    this.type = type;
-  }
-
-  public Set<Map<String, Object>> getData() {
-    return data;
-  }
-
-  public void setData(Set<Map<String, Object>> data) {
-    this.data = data;
-  }
-
-  public String getVersionTag() {
-    return versionTag;
-  }
-
-  public void setVersionTag(String versionTag) {
-    this.versionTag = versionTag;
-  }
-
-  public Integer getVersion() {
-    return version;
-  }
-
-  public void setVersion(Integer version) {
-    this.version = version;
-  }
-
-  public long getCreatedTs() {
-    return createdTs;
-  }
-
-  public void setCreatedTs(long createdTs) {
-    this.createdTs = createdTs;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java
deleted file mode 100644
index 188f1b9..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.ldap;
-
-
-import com.google.gson.annotations.SerializedName;
-
-public class LdapCheckConfigurationRequest implements LdapOperationRequest {
-
-  @SerializedName("AmbariConfiguration")
-  private AmbariConfigurationDTO ambariConfiguration;
-
-  @SerializedName("RequestInfo")
-  private LdapRequestInfo requestInfo;
-
-  public LdapCheckConfigurationRequest() {
-  }
-
-
-  public AmbariConfigurationDTO getAmbariConfiguration() {
-    return ambariConfiguration;
-  }
-
-  public void setAmbariConfiguration(AmbariConfigurationDTO ambariConfiguration) {
-    this.ambariConfiguration = ambariConfiguration;
-  }
-
-  public LdapRequestInfo getRequestInfo() {
-    return requestInfo;
-  }
-
-  public void setRequestInfo(LdapRequestInfo requestInfo) {
-    this.requestInfo = requestInfo;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
new file mode 100644
index 0000000..478d4ff
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ldap;
+
+/**
+ * Enumeration for supported operations related to LDAP configuration.
+ */
+public enum LdapConfigOperation {
+  TEST_CONNECTION("test-connection"),
+  TEST_ATTRIBUTES("test-attributes"),
+  DETECT_ATTRIBUTES("detect-attributes");
+
+  private String actionStr;
+
+  LdapConfigOperation(String actionStr) {
+    this.actionStr = actionStr;
+  }
+
+  public static LdapConfigOperation fromAction(String action) {
+    for (LdapConfigOperation val : LdapConfigOperation.values()) {
+      if (val.action().equals(action)) {
+        return val;
+      }
+    }
+    throw new IllegalStateException("Action [ " + action + " ] is not supported");
+  }
+
+  public String action() {
+    return this.actionStr;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
new file mode 100644
index 0000000..2e478c4
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ldap;
+
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Request object wrapping information for LDAP configuration related request calls.
+ */
+public class LdapConfigurationRequest {
+
+  @SerializedName("AmbariConfiguration")
+  private AmbariConfiguration ambariConfiguration;
+
+  @SerializedName("RequestInfo")
+  private LdapRequestInfo requestInfo;
+
+  public LdapConfigurationRequest() {
+  }
+
+  public AmbariConfiguration getAmbariConfiguration() {
+    return ambariConfiguration;
+  }
+
+  public void setAmbariConfiguration(AmbariConfiguration ambariConfiguration) {
+    this.ambariConfiguration = ambariConfiguration;
+  }
+
+  public LdapRequestInfo getRequestInfo() {
+    return requestInfo;
+  }
+
+  public void setRequestInfo(LdapRequestInfo requestInfo) {
+    this.requestInfo = requestInfo;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
index 52244bc..fc6bd41 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
@@ -74,40 +74,13 @@ public class LdapConfigurationService extends AmbariConfigurationService {
   @Inject
   private static LdapConfigurationFactory ldapConfigurationFactory;
 
-  /**
-   * Actions supported by this endpoint
-   */
-  private enum LdapAction {
-    TEST_CONNECTION("test-connection"),
-    TEST_ATTRIBUTES("test-attributes"),
-    DETECT_ATTRIBUTES("detect-attributes");
-
-    private String actionStr;
-
-    LdapAction(String actionStr) {
-      this.actionStr = actionStr;
-    }
-
-    public static LdapAction fromAction(String action) {
-      for (LdapAction val : LdapAction.values()) {
-        if (val.action().equals(action)) {
-          return val;
-        }
-      }
-      throw new IllegalStateException("Action [ " + action + " ] is not supported");
-    }
-
-    public String action() {
-      return this.actionStr;
-    }
-  }
 
   @POST
   @ApiIgnore // until documented
   @Path("/validate")
   @Consumes(MediaType.APPLICATION_JSON)
   @Produces(MediaType.APPLICATION_JSON)
-  public Response validateConfiguration(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
+  public Response validateConfiguration(LdapConfigurationRequest ldapConfigurationRequest) {
 
     authorize();
 
@@ -116,12 +89,12 @@ public class LdapConfigurationService extends AmbariConfigurationService {
     Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
     try {
 
-      validateRequest(ldapCheckConfigurationRequest);
+      validateRequest(ldapConfigurationRequest);
 
       AmbariLdapConfiguration ambariLdapConfiguration = ldapConfigurationFactory.createLdapConfiguration(
-        ldapCheckConfigurationRequest.getAmbariConfiguration().getData().iterator().next());
+        ldapConfigurationRequest.getAmbariConfiguration().getData().iterator().next());
 
-      LdapAction action = LdapAction.fromAction(ldapCheckConfigurationRequest.getRequestInfo().getAction());
+      LdapConfigOperation action = LdapConfigOperation.fromAction(ldapConfigurationRequest.getRequestInfo().getAction());
       switch (action) {
 
         case TEST_CONNECTION:
@@ -133,7 +106,7 @@ public class LdapConfigurationService extends AmbariConfigurationService {
         case TEST_ATTRIBUTES:
 
           LOGGER.info("Testing LDAP attributes ....");
-          groups = ldapFacade.checkLdapAttibutes(ldapCheckConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
+          groups = ldapFacade.checkLdapAttibutes(ldapConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
           setResult(groups, result);
 
           break;
@@ -161,24 +134,24 @@ public class LdapConfigurationService extends AmbariConfigurationService {
     result.getResultTree().addChild(resource, "payload");
   }
 
-  private void validateRequest(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
+  private void validateRequest(LdapConfigurationRequest ldapConfigurationRequest) {
     String errMsg;
 
-    if (null == ldapCheckConfigurationRequest) {
+    if (null == ldapConfigurationRequest) {
       errMsg = "No ldap configuraiton request provided";
       LOGGER.error(errMsg);
       throw new IllegalArgumentException(errMsg);
     }
 
-    if (null == ldapCheckConfigurationRequest.getRequestInfo()) {
-      errMsg = String.format("No request information provided. Request: [%s]", ldapCheckConfigurationRequest);
+    if (null == ldapConfigurationRequest.getRequestInfo()) {
+      errMsg = String.format("No request information provided. Request: [%s]", ldapConfigurationRequest);
       LOGGER.error(errMsg);
       throw new IllegalArgumentException(errMsg);
     }
 
-    if (null == ldapCheckConfigurationRequest.getAmbariConfiguration()
-      || ldapCheckConfigurationRequest.getAmbariConfiguration().getData().size() != 1) {
-      errMsg = String.format("No / Invalid configuration data provided. Request: [%s]", ldapCheckConfigurationRequest);
+    if (null == ldapConfigurationRequest.getAmbariConfiguration()
+      || ldapConfigurationRequest.getAmbariConfiguration().getData().size() != 1) {
+      errMsg = String.format("No / Invalid configuration data provided. Request: [%s]", ldapConfigurationRequest);
       LOGGER.error(errMsg);
       throw new IllegalArgumentException(errMsg);
     }
@@ -202,7 +175,7 @@ public class LdapConfigurationService extends AmbariConfigurationService {
 
   }
 
-  Set<RoleAuthorization> requiredAuthorizations() {
+  private Set<RoleAuthorization> requiredAuthorizations() {
     return Sets.newHashSet(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java
deleted file mode 100644
index 06f6c40..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * 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.ldap;
-
-public interface LdapOperationRequest {
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationService.java
new file mode 100644
index 0000000..69a641f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationService.java
@@ -0,0 +1,60 @@
+/*
+ * 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.ldap;
+
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.service.AmbariLdapException;
+import org.apache.directory.ldap.client.api.LdapConnection;
+
+/**
+ * Collection of operations for validating ldap configuration.
+ * It's intended to decouple implementations using different libraries.
+ */
+public interface LdapConfigurationService {
+
+  /**
+   * Tests the connection based on the provided configuration.
+   *
+   * @param ldapConnection connection instance
+   * @param configuration  the ambari ldap configuration instance
+   * @throws AmbariLdapException if the connection is not possible
+   */
+  void checkConnection(LdapConnection ldapConnection, AmbariLdapConfiguration configuration) throws AmbariLdapException;
+
+
+  /**
+   * Implements LDAP user related configuration settings validation logic.
+   * Implementers communicate with the LDAP server (search, bind) to validate attributes in the provided configuration
+   * instance
+   *
+   * @param ldapConnection connection instance used to connect to the LDAP server
+   * @param testUserName   the test username
+   * @param testPassword   the test password
+   * @param configuration  the available ldap configuration
+   * @return The DN of the found user entry
+   * @throws AmbariException if the connection couldn't be estabilisheds
+   */
+  String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration configuration) throws AmbariLdapException;
+
+  /**
+   * Checks whether the group related LDAP attributes in the configuration are correct.
+   *
+   * @throws AmbariException if the attributes are not valid
+   */
+  Set<String> checkGroupAttributes(LdapConnection ldapConnection, String userDn, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
deleted file mode 100644
index 7efa3b7..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.ldap;
-
-import java.util.Set;
-
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.ldap.service.AmbariLdapException;
-import org.apache.directory.ldap.client.api.LdapConnection;
-
-/**
- * Collection of operations for validating ldap configuration.
- * It's intended to decouple implementations using different libraries.
- */
-public interface LdapConfigurationValidatorService {
-
-  /**
-   * Tests the connection based on the provided configuration.
-   *
-   * @param ldapConnection connection instance
-   * @param configuration  the ambari ldap configuration instance
-   * @throws AmbariLdapException if the connection is not possible
-   */
-  void checkConnection(LdapConnection ldapConnection, AmbariLdapConfiguration configuration) throws AmbariLdapException;
-
-
-  /**
-   * Implements LDAP user related configuration settings validation logic.
-   * Implementers communicate with the LDAP server (search, bind) to validate attributes in the provided configuration
-   * instance
-   *
-   * @param ldapConnection connection instance used to connect to the LDAP server
-   * @param testUserName   the test username
-   * @param testPassword   the test password
-   * @param configuration  the available ldap configuration
-   * @return The DN of the found user entry
-   * @throws AmbariException if the connection couldn't be estabilisheds
-   */
-  String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration configuration) throws AmbariLdapException;
-
-  /**
-   * Checks whether the group related LDAP attributes in the configuration are correct.
-   *
-   * @throws AmbariException if the attributes are not valid
-   */
-  Set<String> checkGroupAttributes(LdapConnection ldapConnection, String userDn, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
index a4ad2ee..3ae4587 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
@@ -18,7 +18,7 @@ package org.apache.ambari.server.ldap;
 import org.apache.ambari.server.ldap.service.AmbariLdapFacade;
 import org.apache.ambari.server.ldap.service.LdapConnectionService;
 import org.apache.ambari.server.ldap.service.LdapFacade;
-import org.apache.ambari.server.ldap.service.ads.DefaultLdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.service.ads.DefaultLdapConfigurationService;
 import org.apache.ambari.server.ldap.service.ads.DefaultLdapConnectionService;
 
 import com.google.inject.AbstractModule;
@@ -32,7 +32,7 @@ public class LdapModule extends AbstractModule {
   @Override
   protected void configure() {
     bind(LdapFacade.class).to(AmbariLdapFacade.class);
-    bind(LdapConfigurationValidatorService.class).to(DefaultLdapConfigurationValidatorService.class);
+    bind(LdapConfigurationService.class).to(DefaultLdapConfigurationService.class);
     bind(LdapConnectionService.class).to(DefaultLdapConnectionService.class);
 
     install(new FactoryModuleBuilder().build(LdapConfigurationFactory.class));

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
index eec47ce..683ed43 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
@@ -22,7 +22,7 @@ import javax.inject.Inject;
 import javax.inject.Singleton;
 
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.LdapConfigurationService;
 import org.apache.directory.ldap.client.api.LdapConnection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,7 +49,7 @@ public class AmbariLdapFacade implements LdapFacade {
   }
 
   @Inject
-  private LdapConfigurationValidatorService ldapConfigurationValidatorService;
+  private LdapConfigurationService ldapConfigurationService;
 
   @Inject
   private LdapConnectionService ldapConnectionService;
@@ -63,7 +63,7 @@ public class AmbariLdapFacade implements LdapFacade {
     try {
       LOGGER.info("Validating LDAP connection related configuration based on: {}", ambariLdapConfiguration);
       LdapConnection connection = ldapConnectionService.createLdapConnection(ambariLdapConfiguration);
-      ldapConfigurationValidatorService.checkConnection(connection, ambariLdapConfiguration);
+      ldapConfigurationService.checkConnection(connection, ambariLdapConfiguration);
     } catch (AmbariLdapException e) {
       LOGGER.error("Validating LDAP connection configuration failed", e);
       throw e;
@@ -90,10 +90,10 @@ public class AmbariLdapFacade implements LdapFacade {
     LdapConnection ldapConnection = ldapConnectionService.createLdapConnection(ldapConfiguration);
 
     LOGGER.info("Testing LDAP user attributes with test user: {}", userName);
-    String userDn = ldapConfigurationValidatorService.checkUserAttributes(ldapConnection, userName, testUserPass, ldapConfiguration);
+    String userDn = ldapConfigurationService.checkUserAttributes(ldapConnection, userName, testUserPass, ldapConfiguration);
 
     LOGGER.info("Testing LDAP group attributes with test user dn: {}", userDn);
-    Set<String> groups = ldapConfigurationValidatorService.checkGroupAttributes(ldapConnection, userDn, ldapConfiguration);
+    Set<String> groups = ldapConfigurationService.checkGroupAttributes(ldapConnection, userDn, ldapConfiguration);
 
     return groups;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
new file mode 100644
index 0000000..abc9201
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
@@ -0,0 +1,243 @@
+/*
+ * 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.ldap.service.ads;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationService;
+import org.apache.ambari.server.ldap.service.AmbariLdapException;
+import org.apache.ambari.server.ldap.service.LdapConnectionService;
+import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator;
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.Response;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Implementation of the validation logic using the Apache Directory API.
+ */
+@Singleton
+public class DefaultLdapConfigurationService implements LdapConfigurationService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationService.class);
+
+  @Inject
+  private LdapConnectionService ldapConnectionService;
+
+  /**
+   * Facilitating the instantiation
+   */
+  @Inject
+  public DefaultLdapConfigurationService() {
+  }
+
+  @Override
+  public void checkConnection(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    try {
+      bind(ambariLdapConfiguration, ldapConnection);
+    } catch (LdapException e) {
+      LOGGER.error("Could not connect to the LDAP server", e);
+      throw new AmbariLdapException(e);
+    }
+  }
+
+
+  /**
+   * Checks the user attributes provided in the configuration instance by issuing a search for a (known) test user in the LDAP.
+   * Attributes are considered correct if there is at least one entry found.
+   *
+   * Invalid attributes are signaled by throwing an exception.
+   *
+   * @param testUserName            the test username
+   * @param testPassword            the test password
+   * @param ambariLdapConfiguration configuration instance holding ldap configuration details
+   * @return the DN of the test user
+   * @throws AmbariException if the attributes are not valid or any errors occurs
+   */
+  @Override
+  public String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    SearchCursor searchCursor = null;
+    String userDn = null;
+    try {
+      LOGGER.info("Checking user attributes for user {} r ...", testUserName);
+
+      // bind anonimously or with manager data
+      bind(ambariLdapConfiguration, ldapConnection);
+
+      // set up a filter based on the provided attributes
+      String filter = FilterBuilder.and(
+        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
+        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), testUserName))
+        .toString();
+
+      LOGGER.info("Searching for the user: {} using the search filter: {}", testUserName, filter);
+      EntryCursor entryCursor = ldapConnection.search(new Dn(ambariLdapConfiguration.userSearchBase()), filter, SearchScope.SUBTREE);
+
+      // collecting search result entries
+      List<Entry> users = Lists.newArrayList();
+      for (Entry entry : entryCursor) {
+        users.add(entry);
+        userDn = entry.getDn().getNormName();
+      }
+
+      // there should be at least one user found
+      if (users.isEmpty()) {
+        String msg = String.format("There are no users found using the filter: [ %s ]. Try changing the attribute values", filter);
+        LOGGER.error(msg);
+        throw new Exception(msg);
+      }
+
+      LOGGER.info("Attibute validation succeeded. Filter: {}", filter);
+
+    } catch (Exception e) {
+
+      LOGGER.error("User attributes validation failed.", e);
+      throw new AmbariLdapException(e.getMessage(), e);
+
+    } finally {
+      closeResources(ldapConnection, searchCursor);
+    }
+    return userDn;
+  }
+
+
+  @Override
+  public Set<String> checkGroupAttributes(LdapConnection ldapConnection, String userDn, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    SearchCursor searchCursor = null;
+    Set<Response> groupResponses = Sets.newHashSet();
+
+    try {
+      LOGGER.info("Checking group attributes for user dn {} ...", userDn);
+
+      bind(ambariLdapConfiguration, ldapConnection);
+
+      // set up a filter based on the provided attributes
+      String filter = FilterBuilder.and(
+        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.groupObjectClass()),
+        FilterBuilder.equal(ambariLdapConfiguration.groupMemberAttribute(), userDn)
+      ).toString();
+
+      LOGGER.info("Searching for the groups the user dn: {} is member of using the search filter: {}", userDn, filter);
+
+      // assemble a search request
+      SearchRequest searchRequest = new SearchRequestImpl();
+      searchRequest.setFilter(filter);
+      searchRequest.setBase(new Dn(ambariLdapConfiguration.groupSearchBase()));
+      searchRequest.setScope(SearchScope.SUBTREE);
+      searchRequest.addAttributes(ambariLdapConfiguration.groupMemberAttribute(), ambariLdapConfiguration.groupNameAttribute());
+
+      // perform the search
+      searchCursor = ldapConnection.search(searchRequest);
+
+      for (Response response : searchCursor) {
+        groupResponses.add(response);
+      }
+
+    } catch (Exception e) {
+
+      LOGGER.error("User attributes validation failed.", e);
+      throw new AmbariLdapException(e.getMessage(), e);
+
+    } finally {
+      closeResources(ldapConnection, searchCursor);
+    }
+
+    return processGroupResults(groupResponses, ambariLdapConfiguration);
+  }
+
+  /**
+   * Binds to the LDAP server (anonimously or wit manager credentials)
+   *
+   * @param ambariLdapConfiguration configuration instance
+   * @param connection              connection instance
+   * @throws LdapException if the bind operation fails
+   */
+  private void bind(AmbariLdapConfiguration ambariLdapConfiguration, LdapConnection connection) throws LdapException {
+    LOGGER.info("Connecting to LDAP ....");
+    if (!ambariLdapConfiguration.bindAnonimously()) {
+      LOGGER.debug("Anonimous binding not supported, binding with the manager detailas...");
+      connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
+    } else {
+      LOGGER.debug("Binding anonimously ...");
+      connection.bind();
+    }
+
+    if (!connection.isConnected()) {
+      LOGGER.error("Not connected to the LDAP server. Connection instance: {}", connection);
+      throw new IllegalStateException("The connection to the LDAP server is not alive");
+    }
+    LOGGER.info("Connected to LDAP.");
+  }
+
+
+  /**
+   * Extracts meaningful values from the search result.
+   *
+   * @param groupResponses          the result entries returned by the search
+   * @param ambariLdapConfiguration holds the keys of the meaningful attributes
+   * @return a set with the group names the test user belongs to
+   */
+  private Set<String> processGroupResults(Set<Response> groupResponses, AmbariLdapConfiguration ambariLdapConfiguration) {
+    Set<String> groupStrSet = Sets.newHashSet();
+    for (Response response : groupResponses) {
+      Entry entry = ((SearchResultEntryDecorator) response).getEntry();
+      groupStrSet.add(entry.get(ambariLdapConfiguration.groupNameAttribute()).get().getString());
+    }
+
+    LOGGER.debug("Extracted group names from group search responses: {}", groupStrSet);
+    return groupStrSet;
+  }
+
+  private void closeResources(LdapConnection connection, SearchCursor searchCursor) {
+    LOGGER.debug("Housekeeping: closing the connection and the search cursor ...");
+
+    if (null != searchCursor) {
+      // this method is idempotent
+      searchCursor.close();
+    }
+
+    if (null != connection) {
+      try {
+        connection.close();
+      } catch (IOException e) {
+        LOGGER.error("Exception occurred while closing the connection", e);
+      }
+    }
+  }
+
+}
+
+
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java
deleted file mode 100644
index 040983a..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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.ldap.service.ads;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
-import org.apache.ambari.server.ldap.service.AmbariLdapException;
-import org.apache.ambari.server.ldap.service.LdapConnectionService;
-import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator;
-import org.apache.directory.api.ldap.model.constants.SchemaConstants;
-import org.apache.directory.api.ldap.model.cursor.EntryCursor;
-import org.apache.directory.api.ldap.model.cursor.SearchCursor;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.message.Response;
-import org.apache.directory.api.ldap.model.message.SearchRequest;
-import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
-import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.ldap.client.api.LdapConnection;
-import org.apache.directory.ldap.client.api.search.FilterBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-/**
- * Implementation of the validation logic using the Apache Directory API.
- */
-@Singleton
-public class DefaultLdapConfigurationValidatorService implements LdapConfigurationValidatorService {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class);
-
-  @Inject
-  private LdapConnectionService ldapConnectionService;
-
-  /**
-   * Facilitating the instantiation
-   */
-  @Inject
-  public DefaultLdapConfigurationValidatorService() {
-  }
-
-  @Override
-  public void checkConnection(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
-    try {
-      bind(ambariLdapConfiguration, ldapConnection);
-    } catch (LdapException e) {
-      LOGGER.error("Could not connect to the LDAP server", e);
-      throw new AmbariLdapException(e);
-    }
-  }
-
-
-  /**
-   * Checks the user attributes provided in the configuration instance by issuing a search for a (known) test user in the LDAP.
-   * Attributes are considered correct if there is at least one entry found.
-   *
-   * Invalid attributes are signaled by throwing an exception.
-   *
-   * @param testUserName            the test username
-   * @param testPassword            the test password
-   * @param ambariLdapConfiguration configuration instance holding ldap configuration details
-   * @return the DN of the test user
-   * @throws AmbariException if the attributes are not valid or any errors occurs
-   */
-  @Override
-  public String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
-    SearchCursor searchCursor = null;
-    String userDn = null;
-    try {
-      LOGGER.info("Checking user attributes for user {} r ...", testUserName);
-
-      // bind anonimously or with manager data
-      bind(ambariLdapConfiguration, ldapConnection);
-
-      // set up a filter based on the provided attributes
-      String filter = FilterBuilder.and(
-        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
-        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), testUserName))
-        .toString();
-
-      LOGGER.info("Searching for the user: {} using the search filter: {}", testUserName, filter);
-      EntryCursor entryCursor = ldapConnection.search(new Dn(ambariLdapConfiguration.userSearchBase()), filter, SearchScope.SUBTREE);
-
-      // collecting search result entries
-      List<Entry> users = Lists.newArrayList();
-      for (Entry entry : entryCursor) {
-        users.add(entry);
-        userDn = entry.getDn().getNormName();
-      }
-
-      // there should be at least one user found
-      if (users.isEmpty()) {
-        String msg = String.format("There are no users found using the filter: [ %s ]. Try changing the attribute values", filter);
-        LOGGER.error(msg);
-        throw new Exception(msg);
-      }
-
-      LOGGER.info("Attibute validation succeeded. Filter: {}", filter);
-
-    } catch (Exception e) {
-
-      LOGGER.error("User attributes validation failed.", e);
-      throw new AmbariLdapException(e.getMessage(), e);
-
-    } finally {
-      closeResources(ldapConnection, searchCursor);
-    }
-    return userDn;
-  }
-
-
-  @Override
-  public Set<String> checkGroupAttributes(LdapConnection ldapConnection, String userDn, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
-    SearchCursor searchCursor = null;
-    Set<Response> groupResponses = Sets.newHashSet();
-
-    try {
-      LOGGER.info("Checking group attributes for user dn {} ...", userDn);
-
-      bind(ambariLdapConfiguration, ldapConnection);
-
-      // set up a filter based on the provided attributes
-      String filter = FilterBuilder.and(
-        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.groupObjectClass()),
-        FilterBuilder.equal(ambariLdapConfiguration.groupMemberAttribute(), userDn)
-      ).toString();
-
-      LOGGER.info("Searching for the groups the user dn: {} is member of using the search filter: {}", userDn, filter);
-
-      // assemble a search request
-      SearchRequest searchRequest = new SearchRequestImpl();
-      searchRequest.setFilter(filter);
-      searchRequest.setBase(new Dn(ambariLdapConfiguration.groupSearchBase()));
-      searchRequest.setScope(SearchScope.SUBTREE);
-      searchRequest.addAttributes(ambariLdapConfiguration.groupMemberAttribute(), ambariLdapConfiguration.groupNameAttribute());
-
-      // perform the search
-      searchCursor = ldapConnection.search(searchRequest);
-
-      for (Response response : searchCursor) {
-        groupResponses.add(response);
-      }
-
-    } catch (Exception e) {
-
-      LOGGER.error("User attributes validation failed.", e);
-      throw new AmbariLdapException(e.getMessage(), e);
-
-    } finally {
-      closeResources(ldapConnection, searchCursor);
-    }
-
-    return processGroupResults(groupResponses, ambariLdapConfiguration);
-  }
-
-  /**
-   * Binds to the LDAP server (anonimously or wit manager credentials)
-   *
-   * @param ambariLdapConfiguration configuration instance
-   * @param connection              connection instance
-   * @throws LdapException if the bind operation fails
-   */
-  private void bind(AmbariLdapConfiguration ambariLdapConfiguration, LdapConnection connection) throws LdapException {
-    LOGGER.info("Connecting to LDAP ....");
-    if (!ambariLdapConfiguration.bindAnonimously()) {
-      LOGGER.debug("Anonimous binding not supported, binding with the manager detailas...");
-      connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
-    } else {
-      LOGGER.debug("Binding anonimously ...");
-      connection.bind();
-    }
-
-    if (!connection.isConnected()) {
-      LOGGER.error("Not connected to the LDAP server. Connection instance: {}", connection);
-      throw new IllegalStateException("The connection to the LDAP server is not alive");
-    }
-    LOGGER.info("Connected to LDAP.");
-  }
-
-
-  /**
-   * Extracts meaningful values from the search result.
-   *
-   * @param groupResponses          the result entries returned by the search
-   * @param ambariLdapConfiguration holds the keys of the meaningful attributes
-   * @return a set with the group names the test user belongs to
-   */
-  private Set<String> processGroupResults(Set<Response> groupResponses, AmbariLdapConfiguration ambariLdapConfiguration) {
-    Set<String> groupStrSet = Sets.newHashSet();
-    for (Response response : groupResponses) {
-      Entry entry = ((SearchResultEntryDecorator) response).getEntry();
-      groupStrSet.add(entry.get(ambariLdapConfiguration.groupNameAttribute()).get().getString());
-    }
-
-    LOGGER.debug("Extracted group names from group search responses: {}", groupStrSet);
-    return groupStrSet;
-  }
-
-  private void closeResources(LdapConnection connection, SearchCursor searchCursor) {
-    LOGGER.debug("Housekeeping: closing the connection and the search cursor ...");
-
-    if (null != searchCursor) {
-      // this method is idempotent
-      searchCursor.close();
-    }
-
-    if (null != connection) {
-      try {
-        connection.close();
-      } catch (IOException e) {
-        LOGGER.error("Exception occurred while closing the connection", e);
-      }
-    }
-  }
-
-}
-
-
-

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java
index f20cd1f..5e8eac6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java
@@ -46,11 +46,11 @@ public class LDAPServiceTest {
 
 
     // WHEN
-    LdapCheckConfigurationRequest ldapCheckConfigurationRequest = gsonJsonProvider.fromJson(JSON_STRING, LdapCheckConfigurationRequest.class);
-    // LdapCheckConfigurationRequest ldapCheckConfigurationRequest = objectMapper.readValue(JSON_STRING, LdapCheckConfigurationRequest.class);
+    LdapConfigurationRequest ldapConfigurationRequest = gsonJsonProvider.fromJson(JSON_STRING, LdapConfigurationRequest.class);
+    // LdapConfigurationRequest ldapConfigurationRequest = objectMapper.readValue(JSON_STRING, LdapConfigurationRequest.class);
 
     // THEN
-    Assert.assertNotNull(ldapCheckConfigurationRequest);
+    Assert.assertNotNull(ldapConfigurationRequest);
 
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
new file mode 100644
index 0000000..2b7448e
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.ldap.service.ads;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationService;
+import org.apache.ambari.server.ldap.service.LdapConnectionService;
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class DefaultLdapConfigurationServiceTest {
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationService.class);
+  private static final String TEST_USER = "einstein";
+
+  LdapConfigurationService ldapConfigurationService = new DefaultLdapConfigurationService();
+
+
+  @Test
+  public void testCheckAttributes() throws Exception {
+
+    // WHEN
+    LdapConnectionConfig config = new LdapConnectionConfig();
+    config.setLdapHost("localhost");
+    config.setLdapPort(389);
+    LdapConnection connection = new LdapNetworkConnection(config);
+
+    // THEN
+    connection.anonymousBind();
+
+
+    EntryCursor cursor = connection.search("dc=dev,dc=local", "(objectclass=*)", SearchScope.ONELEVEL);
+
+    for (Entry entry : cursor) {
+      assertNotNull(entry);
+      System.out.println(entry);
+    }
+
+    cursor.close();
+
+  }
+
+  @Test
+  public void testCheckUserAttributes() throws Exception {
+    // GIVEN
+    Map<String, Object> ldapPropsMap = Maps.newHashMap();
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_SEARCH_BASE.propertyName(), "dc=example,dc=com");
+
+
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
+    LdapConnectionService connectionService = new DefaultLdapConnectionService();
+    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
+
+    ldapConfigurationService.checkUserAttributes(ldapConnection, "einstein", "", ambariLdapConfiguration);
+  }
+
+  @Test
+  public void testRetrieveGorupsForuser() throws Exception {
+    // GIVEN
+    Map<String, Object> ldapPropsMap = Maps.newHashMap();
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
+
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE.propertyName(), SchemaConstants.UNIQUE_MEMBER_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_SEARCH_BASE.propertyName(), "dc=example,dc=com");
+
+
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
+    LdapConnectionService connectionService = new DefaultLdapConnectionService();
+    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
+
+    ldapConfigurationService.checkGroupAttributes(ldapConnection, "uid=einstein,dc=example,dc=com", ambariLdapConfiguration);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa7d7ec3/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java
deleted file mode 100644
index 1c7f75d..0000000
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.ldap.service.ads;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.util.Map;
-
-import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
-import org.apache.ambari.server.ldap.service.LdapConnectionService;
-import org.apache.directory.api.ldap.model.constants.SchemaConstants;
-import org.apache.directory.api.ldap.model.cursor.EntryCursor;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.ldap.client.api.LdapConnection;
-import org.apache.directory.ldap.client.api.LdapConnectionConfig;
-import org.apache.directory.ldap.client.api.LdapNetworkConnection;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
-
-public class DefaultLdapConfigurationValidatorServiceTest {
-  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class);
-  private static final String TEST_USER = "einstein";
-
-  LdapConfigurationValidatorService ldapConfigurationValidatorService = new DefaultLdapConfigurationValidatorService();
-
-
-  @Test
-  public void testCheckAttributes() throws Exception {
-
-    // WHEN
-    LdapConnectionConfig config = new LdapConnectionConfig();
-    config.setLdapHost("localhost");
-    config.setLdapPort(389);
-    LdapConnection connection = new LdapNetworkConnection(config);
-
-    // THEN
-    connection.anonymousBind();
-
-
-    EntryCursor cursor = connection.search("dc=dev,dc=local", "(objectclass=*)", SearchScope.ONELEVEL);
-
-    for (Entry entry : cursor) {
-      assertNotNull(entry);
-      System.out.println(entry);
-    }
-
-    cursor.close();
-
-  }
-
-  @Test
-  public void testCheckUserAttributes() throws Exception {
-    // GIVEN
-    Map<String, Object> ldapPropsMap = Maps.newHashMap();
-
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
-
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_SEARCH_BASE.propertyName(), "dc=example,dc=com");
-
-
-    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
-    LdapConnectionService connectionService = new DefaultLdapConnectionService();
-    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
-
-    ldapConfigurationValidatorService.checkUserAttributes(ldapConnection, "einstein", "", ambariLdapConfiguration);
-  }
-
-  @Test
-  public void testRetrieveGorupsForuser() throws Exception {
-    // GIVEN
-    Map<String, Object> ldapPropsMap = Maps.newHashMap();
-
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
-
-
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE.propertyName(), SchemaConstants.UNIQUE_MEMBER_AT);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_SEARCH_BASE.propertyName(), "dc=example,dc=com");
-
-
-    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
-    LdapConnectionService connectionService = new DefaultLdapConnectionService();
-    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
-
-    ldapConfigurationValidatorService.checkGroupAttributes(ldapConnection, "uid=einstein,dc=example,dc=com", ambariLdapConfiguration);
-  }
-}
\ No newline at end of file


[38/38] ambari git commit:  AMBARI-21307 Implemented more detectors. Organized the code

Posted by lp...@apache.org.
 AMBARI-21307 Implemented more detectors. Organized the code


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ac71c44c
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ac71c44c
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ac71c44c

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: ac71c44c53f9170fdc3f94342a381a27bf42d5d6
Parents: 7b91bc5
Author: lpuskas <lp...@apache.org>
Authored: Tue Sep 12 11:58:45 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:32 2017 +0200

----------------------------------------------------------------------
 .../server/ldap/AmbariLdapConfiguration.java    |   1 +
 .../ads/DefaultAttributeDetectionService.java   | 134 ++++++++++++++-----
 .../ldap/service/ads/ObjectClassDetector.java   |  81 -----------
 .../ads/OccurranceAndWeightBasedDetector.java   |  81 -----------
 .../service/ads/UserNameAttributeDetector.java  |  75 -----------
 .../ads/detectors/GroupMemberAttrDetector.java  |  56 ++++++++
 .../ads/detectors/GroupNameAttrDetector.java    |  61 +++++++++
 .../ads/detectors/GroupObjectClassDetector.java |  64 +++++++++
 .../OccurranceAndWeightBasedDetector.java       | 103 ++++++++++++++
 .../detectors/UserGroupMemberAttrDetector.java  |  56 ++++++++
 .../ads/detectors/UserNameAttrDetector.java     |  60 +++++++++
 .../ads/detectors/UserObjectClassDetector.java  |  64 +++++++++
 .../DefaultAttributeDetectionServiceTest.java   |  10 +-
 13 files changed, 571 insertions(+), 275 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
index e28c6ed..ebb567d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
@@ -56,6 +56,7 @@ public class AmbariLdapConfiguration {
 
     USER_OBJECT_CLASS("ambari.ldap.attributes.user.object_class"),
     USER_NAME_ATTRIBUTE("ambari.ldap.attributes.user.name_attr"),
+    USER_GROUP_MEMBER_ATTRIBUTE("ambari.ldap.attributes.user.group_member_attr"),
     USER_SEARCH_BASE("ambari.ldap.attributes.user.search_base"),
 
     GROUP_OBJECT_CLASS("ambari.ldap.attributes.group.object_class"),

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
index 710adf1..b3a4fde 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
@@ -14,15 +14,18 @@
 
 package org.apache.ambari.server.ldap.service.ads;
 
-import java.util.Set;
-
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
 import org.apache.ambari.server.ldap.service.AmbariLdapException;
-import org.apache.ambari.server.ldap.service.AttributeDetector;
 import org.apache.ambari.server.ldap.service.LdapAttributeDetectionService;
+import org.apache.ambari.server.ldap.service.ads.detectors.GroupMemberAttrDetector;
+import org.apache.ambari.server.ldap.service.ads.detectors.GroupNameAttrDetector;
+import org.apache.ambari.server.ldap.service.ads.detectors.GroupObjectClassDetector;
+import org.apache.ambari.server.ldap.service.ads.detectors.UserGroupMemberAttrDetector;
+import org.apache.ambari.server.ldap.service.ads.detectors.UserNameAttrDetector;
+import org.apache.ambari.server.ldap.service.ads.detectors.UserObjectClassDetector;
 import org.apache.directory.api.ldap.model.cursor.SearchCursor;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.message.Response;
@@ -37,24 +40,29 @@ import org.apache.directory.ldap.client.api.search.FilterBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Sets;
-
 @Singleton
 public class DefaultAttributeDetectionService implements LdapAttributeDetectionService<LdapConnection> {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAttributeDetectionService.class);
   private static final int SAMPLE_RESULT_SIZE = 50;
 
-  // ordered list of possible username attribute values (the most significant valus should be first)
 
-  private static final Set<String> USER_OBJECT_CLASS_VALUES = Sets.newHashSet("person", "posixAccount");
-  private static final Set<String> USER_GROUP_MEMBER_ATTR_VALUES = Sets.newHashSet("memberOf", "ismemberOf");
+  @Inject
+  private UserNameAttrDetector userNameAttrDetector = new UserNameAttrDetector(); // todo remove instantition
+
+  @Inject
+  private UserObjectClassDetector userObjectClassDetector = new UserObjectClassDetector(); // todo remove instantition
 
   @Inject
-  private UserNameAttributeDetector userNameAttrDetector = new UserNameAttributeDetector(); // todo remove instantition
+  private UserGroupMemberAttrDetector userGroupMemberAttrDetector = new UserGroupMemberAttrDetector(); // todo remove instantition
 
   @Inject
-  private ObjectClassDetector objectClassDetector = new ObjectClassDetector(); // todo remove instantition
+  private GroupNameAttrDetector groupNameAttrDetector = new GroupNameAttrDetector(); // todo remove instantition
+
+  @Inject
+  private GroupObjectClassDetector groupObjectClassDetector = new GroupObjectClassDetector(); // todo remove instantition
+
+  private GroupMemberAttrDetector groupMemberAttrDetector = new GroupMemberAttrDetector(); // todo remove instantition
 
   @Inject
   public DefaultAttributeDetectionService() {
@@ -76,7 +84,7 @@ public class DefaultAttributeDetectionService implements LdapAttributeDetectionS
       // todo should the bind operation be done in the facade?
       connection.bind(ambariLdapConfiguration.bindDn(), ambariLdapConfiguration.bindPassword());
 
-      SearchRequest searchRequest = assembleSearchRequest(ambariLdapConfiguration);
+      SearchRequest searchRequest = assembleUserSearchRequest(ambariLdapConfiguration);
 
       // do the search
       searchCursor = connection.search(searchRequest);
@@ -95,15 +103,19 @@ public class DefaultAttributeDetectionService implements LdapAttributeDetectionS
 
         if (response instanceof SearchResultEntry) {
           Entry resultEntry = ((SearchResultEntry) response).getEntry();
-          LOGGER.info("Processing sample entry: [{}]", resultEntry.getDn());
+          LOGGER.info("Processing sample entry with dn: [{}]", resultEntry.getDn());
+
           userNameAttrDetector.collect(resultEntry);
-          objectClassDetector.collect(resultEntry);
+          userObjectClassDetector.collect(resultEntry);
+          userGroupMemberAttrDetector.collect(resultEntry);
+
           processedUserCnt++;
         }
       }
 
       ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.USER_NAME_ATTRIBUTE, userNameAttrDetector.detect());
-      ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.USER_OBJECT_CLASS, objectClassDetector.detect());
+      ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.USER_OBJECT_CLASS, userObjectClassDetector.detect());
+      ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.USER_GROUP_MEMBER_ATTRIBUTE, userGroupMemberAttrDetector.detect());
 
       LOGGER.info("Decorated ambari ldap config : [{}]", ambariLdapConfiguration);
 
@@ -120,25 +132,72 @@ public class DefaultAttributeDetectionService implements LdapAttributeDetectionS
     return ambariLdapConfiguration;
   }
 
-  private void detectUserAttributes(Entry resultEntry, AttributeDetector attributeDetector) {
 
-    attributeDetector.collect(resultEntry);
+  @Override
+  public AmbariLdapConfiguration detectLdapGroupAttributes(LdapConnection connection, AmbariLdapConfiguration ambariLdapConfiguration) {
+    LOGGER.info("Detecting LDAP group attributes ...");
 
-//    Set<String> objectClasses = detectUserObjectClass(resultEntry);
-//    if (!objectClasses.isEmpty()) {
-//      ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.USER_OBJECT_CLASS, StringUtils.join(objectClasses, ","));
-//    }
+    // perform a search using the user search base
+    if (Strings.isEmpty(ambariLdapConfiguration.groupSearchBase())) {
+      LOGGER.warn("No group search base provided");
+      return ambariLdapConfiguration;
+    }
 
+    SearchCursor searchCursor = null;
 
-  }
+    try {
+      // todo should the bind operation be done in the facade?
+      connection.bind(ambariLdapConfiguration.bindDn(), ambariLdapConfiguration.bindPassword());
 
-  @Override
-  public AmbariLdapConfiguration detectLdapGroupAttributes(LdapConnection connection, AmbariLdapConfiguration ambariLdapConfiguration) {
-    LOGGER.info("Detecting LDAP group attributes ...");
-    return null;
+      SearchRequest searchRequest = assembleGroupSearchRequest(ambariLdapConfiguration);
+
+      // do the search
+      searchCursor = connection.search(searchRequest);
+
+      int processedGroupCnt = 0;
+
+      while (searchCursor.next()) {
+
+        if (processedGroupCnt >= SAMPLE_RESULT_SIZE) {
+          LOGGER.debug("The maximum number of results for attribute detection has exceeded. Quit  detection.");
+          break;
+        }
+
+        Response response = searchCursor.get();
+        // process the SearchResultEntry
+
+        if (response instanceof SearchResultEntry) {
+          Entry resultEntry = ((SearchResultEntry) response).getEntry();
+          LOGGER.info("Processing sample entry with dn: [{}]", resultEntry.getDn());
+
+          groupNameAttrDetector.collect(resultEntry);
+          groupObjectClassDetector.collect(resultEntry);
+          groupMemberAttrDetector.collect(resultEntry);
+
+          processedGroupCnt++;
+        }
+      }
+
+      ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.GROUP_NAME_ATTRIBUTE, groupNameAttrDetector.detect());
+      ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.GROUP_OBJECT_CLASS, groupObjectClassDetector.detect());
+      ambariLdapConfiguration.setValueFor(AmbariLdapConfiguration.AmbariLdapConfig.GROUP_MEMBER_ATTRIBUTE, groupMemberAttrDetector.detect());
+
+      LOGGER.info("Decorated ambari ldap config : [{}]", ambariLdapConfiguration);
+
+    } catch (Exception e) {
+
+      LOGGER.error("Ldap operation failed", e);
+    } finally {
+      // housekeeping
+      if (null != searchCursor) {
+        searchCursor.close();
+      }
+    }
+
+    return ambariLdapConfiguration;
   }
 
-  private SearchRequest assembleSearchRequest(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+  private SearchRequest assembleUserSearchRequest(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
     try {
 
       SearchRequest req = new SearchRequestImpl();
@@ -157,18 +216,23 @@ public class DefaultAttributeDetectionService implements LdapAttributeDetectionS
     }
   }
 
+  private SearchRequest assembleGroupSearchRequest(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    try {
 
-  private Set<String> detectUserObjectClass(Entry entry) {
-    LOGGER.info("Detecting user object class. Attributes: {}", entry.getAttributes());
-    throw new UnsupportedOperationException("Not yet implemented");
-  }
+      SearchRequest req = new SearchRequestImpl();
+      req.setScope(SearchScope.SUBTREE);
+      req.addAttributes("*");
+      req.setTimeLimit(0);
+      req.setBase(new Dn(ambariLdapConfiguration.groupSearchBase()));
+      // the filter must be set!
+      req.setFilter(FilterBuilder.present(ambariLdapConfiguration.dnAttribute()).toString());
 
-  private String detectGroupNameAttribute(Entry entry) {
-    throw new UnsupportedOperationException("Not yet implemented");
-  }
+      return req;
 
-  private Set<String> detectGroupObjectClass(Entry entry) {
-    throw new UnsupportedOperationException("Not yet implemented");
+    } catch (Exception e) {
+      LOGGER.error("Could not assemble ldap search request", e);
+      throw new AmbariLdapException(e);
+    }
   }
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/ObjectClassDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/ObjectClassDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/ObjectClassDetector.java
deleted file mode 100644
index 2613517..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/ObjectClassDetector.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.ldap.service.ads;
-
-import java.util.Map;
-
-import javax.inject.Inject;
-
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
-
-public class ObjectClassDetector extends OccurranceAndWeightBasedDetector {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(ObjectClassDetector.class);
-  private Map<String, Integer> occurranceMap = Maps.newHashMap();
-  private Map<String, Integer> weightsMap = Maps.newHashMap();
-
-
-  private enum ObjectClassValue {
-    PERSON("person", 1),
-    POSIX_ACCOUNT("posixAccount", 1);
-
-    private String ocVal;
-    private Integer weight;
-
-    ObjectClassValue(String attr, Integer weght) {
-      this.ocVal = attr;
-      this.weight = weght;
-    }
-
-    Integer weight() {
-      return this.weight;
-    }
-
-    String ocVal() {
-      return this.ocVal;
-    }
-
-  }
-
-  @Inject
-  public ObjectClassDetector() {
-    for (ObjectClassValue ocVal : ObjectClassValue.values()) {
-      occurranceMap.put(ocVal.ocVal(), 0);
-      weightsMap.put(ocVal.ocVal(), ocVal.weight());
-    }
-
-  }
-
-  @Override
-  protected Map<String, Integer> occurranceMap() {
-    return occurranceMap;
-  }
-
-  @Override
-  protected Map<String, Integer> weightsMap() {
-    return weightsMap;
-  }
-
-  @Override
-  protected boolean applies(Entry entry, String value) {
-    LOGGER.info("Checking for object class [{}] in entry [{}]", value, entry.getDn());
-    return entry.hasObjectClass(value);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/OccurranceAndWeightBasedDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/OccurranceAndWeightBasedDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/OccurranceAndWeightBasedDetector.java
deleted file mode 100644
index 32dc238..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/OccurranceAndWeightBasedDetector.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.ldap.service.ads;
-
-import java.util.Map;
-
-import org.apache.ambari.server.ldap.service.AttributeDetector;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class OccurranceAndWeightBasedDetector implements AttributeDetector<Entry> {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(OccurranceAndWeightBasedDetector.class);
-
-  protected abstract Map<String, Integer> occurranceMap();
-
-  protected abstract Map<String, Integer> weightsMap();
-
-  protected abstract boolean applies(Entry entry, String value);
-
-  @Override
-  public String detect() {
-    Map.Entry<String, Integer> selectedEntry = null;
-
-    for (Map.Entry<String, Integer> entry : occurranceMap().entrySet()) {
-      if (selectedEntry == null) {
-
-        selectedEntry = entry;
-        LOGGER.info("Initial name attribute: {}", selectedEntry);
-        continue;
-
-      }
-
-      if (selectedEntry.getValue() < entry.getValue()) {
-
-        LOGGER.info("Changing potential name attribute from : [{}] to: [{}]", selectedEntry, entry);
-        selectedEntry = entry;
-
-      }
-    }
-    return selectedEntry.getKey();
-  }
-
-  @Override
-  public void collect(Entry entry) {
-    LOGGER.info("Detecting ldap attributes/values ...");
-
-    for (String attributeValue : occurranceMap().keySet()) {
-      if (applies(entry, attributeValue)) {
-
-        Integer cnt = occurranceMap().get(attributeValue).intValue();
-        if (weightsMap().containsKey(attributeValue)) {
-          cnt = cnt + weightsMap().get(attributeValue);
-        } else {
-          cnt = cnt + 1;
-        }
-        occurranceMap().put(attributeValue, cnt);
-
-        LOGGER.info("Collected potential name attr: {}, count: {}", attributeValue, cnt);
-
-      } else {
-        LOGGER.info("The result entry doesn't contain the attribute: [{}]", attributeValue);
-      }
-    }
-  }
-
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/UserNameAttributeDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/UserNameAttributeDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/UserNameAttributeDetector.java
deleted file mode 100644
index bbb4b43..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/UserNameAttributeDetector.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.ldap.service.ads;
-
-import java.util.Map;
-
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
-
-public class UserNameAttributeDetector extends OccurranceAndWeightBasedDetector {
-  private static final Logger LOGGER = LoggerFactory.getLogger(UserNameAttributeDetector.class);
-
-  private Map<String, Integer> occurranceMap = Maps.newHashMap();
-  private Map<String, Integer> weightsMap = Maps.newHashMap();
-
-  private enum NameAttrs {
-    SAM_ACCOUNT_NAME("sAMAccountName", 5),
-    UID("uid", 3),
-    CN("cn", 1);
-
-    private String attrName;
-    private Integer weight;
-
-    NameAttrs(String attr, Integer weght) {
-      this.attrName = attr;
-      this.weight = weght;
-    }
-
-    Integer weight() {
-      return this.weight;
-    }
-
-    String attrName() {
-      return this.attrName;
-    }
-
-  }
-
-  public UserNameAttributeDetector() {
-    for (NameAttrs nameAttr : NameAttrs.values()) {
-      occurranceMap.put(nameAttr.attrName(), 0);
-      weightsMap.put(nameAttr.attrName(), nameAttr.weight());
-    }
-  }
-
-  protected Map<String, Integer> occurranceMap() {
-    return occurranceMap;
-  }
-
-  protected Map<String, Integer> weightsMap() {
-    return weightsMap;
-  }
-
-  @Override
-  protected boolean applies(Entry entry, String value) {
-    LOGGER.info("Checking for attribute  [{}] in entry [{}]", value, entry.getDn());
-    return entry.containsAttribute(value);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java
new file mode 100644
index 0000000..6931736
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java
@@ -0,0 +1,56 @@
+/*
+ * 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.ldap.service.ads.detectors;
+
+import org.apache.directory.api.ldap.model.entry.Entry;
+
+public class GroupMemberAttrDetector extends OccurranceAndWeightBasedDetector {
+
+  private enum GroupMemberAttr {
+
+    MEMBER("member", 1),
+    MEMBER_UID("memberUid", 1),
+    UNIQUE_MEMBER("uniqueMember", 1);
+
+    private String attrName;
+    private Integer weight;
+
+    GroupMemberAttr(String attr, Integer weght) {
+      this.attrName = attr;
+      this.weight = weght;
+    }
+
+    Integer weight() {
+      return this.weight;
+    }
+
+    String attrName() {
+      return this.attrName;
+    }
+
+  }
+
+  public GroupMemberAttrDetector() {
+    for (GroupMemberAttr groupMemberAttr : GroupMemberAttr.values()) {
+      occurranceMap().put(groupMemberAttr.attrName(), 0);
+      weightsMap().put(groupMemberAttr.attrName(), groupMemberAttr.weight());
+    }
+  }
+
+  @Override
+  protected boolean applies(Entry entry, String value) {
+    return entry.containsAttribute(value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupNameAttrDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupNameAttrDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupNameAttrDetector.java
new file mode 100644
index 0000000..f868383
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupNameAttrDetector.java
@@ -0,0 +1,61 @@
+/*
+ * 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.ldap.service.ads.detectors;
+
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GroupNameAttrDetector extends OccurranceAndWeightBasedDetector {
+  private static final Logger LOGGER = LoggerFactory.getLogger(UserNameAttrDetector.class);
+
+  private enum GroupNameAttr {
+
+    DISTINGUISHED_NAME("distinguishedName", 1),
+
+    CN("cn", 1);
+
+    private String attrName;
+    private Integer weight;
+
+    GroupNameAttr(String attr, Integer weght) {
+      this.attrName = attr;
+      this.weight = weght;
+    }
+
+    Integer weight() {
+      return this.weight;
+    }
+
+    String attrName() {
+      return this.attrName;
+    }
+
+  }
+
+  public GroupNameAttrDetector() {
+
+    for (GroupNameAttr groupNameAttr : GroupNameAttr.values()) {
+      occurranceMap().put(groupNameAttr.attrName(), 0);
+      weightsMap().put(groupNameAttr.attrName(), groupNameAttr.weight());
+    }
+  }
+
+
+  @Override
+  protected boolean applies(Entry entry, String value) {
+    return entry.containsAttribute(value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupObjectClassDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupObjectClassDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupObjectClassDetector.java
new file mode 100644
index 0000000..fddc5a5
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupObjectClassDetector.java
@@ -0,0 +1,64 @@
+/*
+ * 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.ldap.service.ads.detectors;
+
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GroupObjectClassDetector extends OccurranceAndWeightBasedDetector {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(GroupObjectClassDetector.class);
+
+  private enum ObjectClassValue {
+
+    GROUP("group", 1),
+
+    GROUP_OF_NAMES("groupOfNames", 1),
+
+    POSIX_GROUP("posixGroup", 1),
+
+    GROUP_OF_UNIQUE_NAMES("groupOfUniqueNames", 1);
+
+    private String ocVal;
+    private Integer weight;
+
+    ObjectClassValue(String attr, Integer weght) {
+      this.ocVal = attr;
+      this.weight = weght;
+    }
+
+    Integer weight() {
+      return this.weight;
+    }
+
+    String ocVal() {
+      return this.ocVal;
+    }
+
+  }
+
+  public GroupObjectClassDetector() {
+    for (ObjectClassValue ocVal : ObjectClassValue.values()) {
+      occurranceMap().put(ocVal.ocVal(), 0);
+      weightsMap().put(ocVal.ocVal(), ocVal.weight());
+    }
+  }
+
+  @Override
+  protected boolean applies(Entry entry, String value) {
+    return entry.hasObjectClass(value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/OccurranceAndWeightBasedDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/OccurranceAndWeightBasedDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/OccurranceAndWeightBasedDetector.java
new file mode 100644
index 0000000..8aaf6c1
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/OccurranceAndWeightBasedDetector.java
@@ -0,0 +1,103 @@
+/*
+ * 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.ldap.service.ads.detectors;
+
+import java.util.Map;
+
+import org.apache.ambari.server.ldap.service.AttributeDetector;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public abstract class OccurranceAndWeightBasedDetector implements AttributeDetector<Entry> {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(OccurranceAndWeightBasedDetector.class);
+
+  private Map<String, Integer> occurranceMap = Maps.newHashMap();
+  private Map<String, Integer> weightsMap = Maps.newHashMap();
+
+  protected Map<String, Integer> occurranceMap() {
+    return occurranceMap;
+  }
+
+  protected Map<String, Integer> weightsMap() {
+    return weightsMap;
+  }
+
+
+  protected abstract boolean applies(Entry entry, String value);
+
+  @Override
+  public String detect() {
+    LOGGER.info("Calculating the most probable attribute/value ...");
+    Map.Entry<String, Integer> selectedEntry = null;
+
+    for (Map.Entry<String, Integer> entry : occurranceMap().entrySet()) {
+      if (selectedEntry == null) {
+
+        selectedEntry = entry;
+        LOGGER.debug("Initial attribute / value entry: {}", selectedEntry);
+        continue;
+
+      }
+
+      if (selectedEntry.getValue() < entry.getValue()) {
+
+        LOGGER.info("Changing potential attribute / value entry from : [{}] to: [{}]", selectedEntry, entry);
+        selectedEntry = entry;
+
+      }
+    }
+
+    // check whether the selected entry is valid (has occured in the sample result set)
+    String detectedVal = "N/A";
+
+    if (selectedEntry.getValue() > 0) {
+      detectedVal = selectedEntry.getKey();
+    } else {
+      LOGGER.warn("Unable to detect attribute or attribute value");
+    }
+
+    LOGGER.info("Detected attribute or value: [{}]", detectedVal);
+    return detectedVal;
+  }
+
+  @Override
+  public void collect(Entry entry) {
+    LOGGER.info("Collecting ldap attributes/values form entry with dn: [{]]", entry.getDn());
+
+    for (String attributeValue : occurranceMap().keySet()) {
+      if (applies(entry, attributeValue)) {
+
+        Integer cnt = occurranceMap().get(attributeValue).intValue();
+        if (weightsMap().containsKey(attributeValue)) {
+          cnt = cnt + weightsMap().get(attributeValue);
+        } else {
+          cnt = cnt + 1;
+        }
+        occurranceMap().put(attributeValue, cnt);
+
+        LOGGER.info("Collected potential name attr: {}, count: {}", attributeValue, cnt);
+
+      } else {
+        LOGGER.info("The result entry doesn't contain the attribute: [{}]", attributeValue);
+      }
+    }
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserGroupMemberAttrDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserGroupMemberAttrDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserGroupMemberAttrDetector.java
new file mode 100644
index 0000000..c3f2ab4
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserGroupMemberAttrDetector.java
@@ -0,0 +1,56 @@
+/*
+ * 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.ldap.service.ads.detectors;
+
+import org.apache.directory.api.ldap.model.entry.Entry;
+
+public class UserGroupMemberAttrDetector extends OccurranceAndWeightBasedDetector {
+  private static String[] userGroupMemAttrValues = {"memberOf", "ismemberOf"};
+
+  private enum UserGroupMemberAttr {
+
+    MEMBER_OF("memberOf", 1),
+    IS_MEMBER_OF("ismemberOf", 1);
+
+    private String attrName;
+    private Integer weight;
+
+    UserGroupMemberAttr(String attr, Integer weght) {
+      this.attrName = attr;
+      this.weight = weght;
+    }
+
+    Integer weight() {
+      return this.weight;
+    }
+
+    String attrName() {
+      return this.attrName;
+    }
+
+  }
+
+  public UserGroupMemberAttrDetector() {
+    for (UserGroupMemberAttr userGroupMemberAttr : UserGroupMemberAttr.values()) {
+      occurranceMap().put(userGroupMemberAttr.attrName(), 0);
+      weightsMap().put(userGroupMemberAttr.attrName(), userGroupMemberAttr.weight);
+    }
+  }
+
+  @Override
+  protected boolean applies(Entry entry, String value) {
+    return entry.containsAttribute(value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserNameAttrDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserNameAttrDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserNameAttrDetector.java
new file mode 100644
index 0000000..40bf09b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserNameAttrDetector.java
@@ -0,0 +1,60 @@
+/*
+ * 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.ldap.service.ads.detectors;
+
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UserNameAttrDetector extends OccurranceAndWeightBasedDetector {
+  private static final Logger LOGGER = LoggerFactory.getLogger(UserNameAttrDetector.class);
+
+  private enum UserNameAttrs {
+    SAM_ACCOUNT_NAME("sAMAccountName", 5),
+    UID("uid", 3),
+    CN("cn", 1);
+
+    private String attrName;
+    private Integer weight;
+
+    UserNameAttrs(String attr, Integer weght) {
+      this.attrName = attr;
+      this.weight = weght;
+    }
+
+    Integer weight() {
+      return this.weight;
+    }
+
+    String attrName() {
+      return this.attrName;
+    }
+
+  }
+
+  public UserNameAttrDetector() {
+    for (UserNameAttrs nameAttr : UserNameAttrs.values()) {
+      occurranceMap().put(nameAttr.attrName(), 0);
+      weightsMap().put(nameAttr.attrName(), nameAttr.weight());
+    }
+  }
+
+  @Override
+  protected boolean applies(Entry entry, String value) {
+    LOGGER.info("Checking for attribute  [{}] in entry [{}]", value, entry.getDn());
+    return entry.containsAttribute(value);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java
new file mode 100644
index 0000000..97b3c52
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java
@@ -0,0 +1,64 @@
+/*
+ * 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.ldap.service.ads.detectors;
+
+import javax.inject.Inject;
+
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UserObjectClassDetector extends OccurranceAndWeightBasedDetector {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(UserObjectClassDetector.class);
+
+  private enum ObjectClassValue {
+    PERSON("person", 1),
+    POSIX_ACCOUNT("posixAccount", 1);
+
+    private String ocVal;
+    private Integer weight;
+
+    ObjectClassValue(String attr, Integer weght) {
+      this.ocVal = attr;
+      this.weight = weght;
+    }
+
+    Integer weight() {
+      return this.weight;
+    }
+
+    String ocVal() {
+      return this.ocVal;
+    }
+
+  }
+
+  @Inject
+  public UserObjectClassDetector() {
+    for (ObjectClassValue ocVal : ObjectClassValue.values()) {
+      occurranceMap().put(ocVal.ocVal(), 0);
+      weightsMap().put(ocVal.ocVal(), ocVal.weight());
+    }
+
+  }
+
+  @Override
+  protected boolean applies(Entry entry, String value) {
+    LOGGER.info("Checking for object class [{}] in entry [{}]", value, entry.getDn());
+    return entry.hasObjectClass(value);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ac71c44c/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
index 5cddf1a..08f2d6c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
@@ -32,6 +32,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.Maps;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 
 public class DefaultAttributeDetectionServiceTest {
 
@@ -78,9 +80,12 @@ public class DefaultAttributeDetectionServiceTest {
 
     // WHEN
     AmbariLdapConfiguration config = attributeDetectionService.detectLdapUserAttributes(ldapConnection, ambariLdapConfiguration);
+    config = attributeDetectionService.detectLdapGroupAttributes(ldapConnection, ambariLdapConfiguration);
 
-    // THEN
+    Gson gson = new GsonBuilder().create();
+    LOGGER.info(gson.toJson(config));
 
+    // THEN
     ldapConnection.close();
 
   }
@@ -95,9 +100,8 @@ public class DefaultAttributeDetectionServiceTest {
     ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.BIND_PASSWORD.key(), "password");
     ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.DN_ATTRIBUTE.key(), SchemaConstants.CN_AT);
 
-    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_OBJECT_CLASS.key(), SchemaConstants.PERSON_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_NAME_ATTRIBUTE.key(), SchemaConstants.UID_AT);
     ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_SEARCH_BASE.key(), "dc=example,dc=com");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.GROUP_SEARCH_BASE.key(), "dc=example,dc=com");
 
     return ldapPropsMap;
 


[15/38] ambari git commit: AMBARI-21947. Ambari updates database/tables location from intended remote HDFS to local HDFS (aonishuk)

Posted by lp...@apache.org.
AMBARI-21947. Ambari updates database/tables location from intended remote HDFS to local HDFS (aonishuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/18ae06d3
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/18ae06d3
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/18ae06d3

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 18ae06d3e49c98f919b666deca7c42b460ee204f
Parents: fa0ecc4
Author: Andrew Onishuk <ao...@hortonworks.com>
Authored: Wed Sep 13 14:27:24 2017 +0300
Committer: Andrew Onishuk <ao...@hortonworks.com>
Committed: Wed Sep 13 14:27:24 2017 +0300

----------------------------------------------------------------------
 .../HIVE/0.12.0.2.0/package/scripts/hive_service.py            | 4 ++++
 .../HIVE/0.12.0.2.0/package/scripts/params_linux.py            | 3 +++
 .../resources/stacks/HDP/2.0.6/configuration/cluster-env.xml   | 6 ++++++
 3 files changed, 13 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/18ae06d3/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive_service.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive_service.py b/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive_service.py
index 1f2b644..2412bf9 100644
--- a/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive_service.py
+++ b/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive_service.py
@@ -168,6 +168,10 @@ def validate_connection(target_path_to_jdbc, hive_lib_path):
 def check_fs_root(conf_dir, execution_path):
   import params
 
+  if not params.manage_hive_fsroot:
+    Logger.info("Skipping fs root check as cluster-env/manage_hive_fsroot is disabled")
+    return
+
   if not params.fs_root.startswith("hdfs://"):
     Logger.info("Skipping fs root check as fs_root does not start with hdfs://")
     return

http://git-wip-us.apache.org/repos/asf/ambari/blob/18ae06d3/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/params_linux.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/params_linux.py b/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/params_linux.py
index 9ba1f99..ceeac79 100644
--- a/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/params_linux.py
+++ b/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/params_linux.py
@@ -867,3 +867,6 @@ druid_storage_dir = ""
 if 'druid-common' in config['configurations'] \
         and 'druid.storage.storageDirectory' in config['configurations']['druid-common']:
   druid_storage_dir = config['configurations']['druid-common']['druid.storage.storageDirectory']
+
+
+manage_hive_fsroot = default('/configurations/cluster-env/manage_hive_fsroot', True)

http://git-wip-us.apache.org/repos/asf/ambari/blob/18ae06d3/ambari-server/src/main/resources/stacks/HDP/2.0.6/configuration/cluster-env.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/configuration/cluster-env.xml b/ambari-server/src/main/resources/stacks/HDP/2.0.6/configuration/cluster-env.xml
index 45f3b42..55b9cd3 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/configuration/cluster-env.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/configuration/cluster-env.xml
@@ -357,4 +357,10 @@ gpgcheck=0</value>
     <description>Timeout for safemode exit, during namenode rolling restart</description>
     <on-ambari-upgrade add="true"/>
   </property>
+  <property>
+    <name>manage_hive_fsroot</name>
+    <value>true</value>
+    <description>If flag is set to true, ambari will manage fsroot for Hive, by setting it to fs.defautlFS of local HDFS</description>
+    <on-ambari-upgrade add="false"/>
+  </property>
 </configuration>


[29/38] ambari git commit: AMBARI-21307 Draft implementation of the group related attributes

Posted by lp...@apache.org.
AMBARI-21307 Draft implementation of the group related attributes


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3ad545a4
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3ad545a4
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3ad545a4

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 3ad545a4620e1f0f27d109a1dbc5631012c624d9
Parents: 43dbbc9
Author: lpuskas <lp...@apache.org>
Authored: Tue Aug 8 13:54:29 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:30 2017 +0200

----------------------------------------------------------------------
 .../server/ldap/AmbariLdapConfiguration.java    |  22 +-
 .../ldap/LdapConfigurationValidatorService.java |  34 +--
 .../apache/ambari/server/ldap/LdapModule.java   |   4 +-
 .../server/ldap/service/AmbariLdapFacade.java   |  25 +-
 .../ldap/service/LdapConnectionService.java     |  35 +++
 .../ambari/server/ldap/service/LdapFacade.java  |   9 +-
 .../ad/AdLdapConfigurationValidatorService.java | 177 --------------
 ...efaultLdapConfigurationValidatorService.java | 232 +++++++++++++++++++
 .../ad/DefaultLdapConnectionService.java        |  63 +++++
 .../service/ad/LdapConfigurationConverter.java  |  50 ----
 ...AdLdapConfigurationValidatorServiceTest.java | 129 -----------
 ...ltLdapConfigurationValidatorServiceTest.java | 156 +++++++++++++
 12 files changed, 552 insertions(+), 384 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
index 519f400..a6ff80b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
@@ -53,7 +53,7 @@ public class AmbariLdapConfiguration {
     GROUP_OBJECT_CLASS("ambari.ldap.group.object.class"),
     GROUP_NAME_ATTRIBUTE("ambari.ldap.group.name.attribute"),
     GROUP_MEMBER_ATTRIBUTE("ambari.ldap.group.member.attribute"),
-    GROUP_SEARCH_BASE("ambari.ldap.group.member.attribute"),
+    GROUP_SEARCH_BASE("ambari.ldap.group.search.base"),
     DN_ATTRIBUTE("authentication.ldap.dnAttribute");
 
     private String propertyName;
@@ -126,4 +126,24 @@ public class AmbariLdapConfiguration {
     return (String) configurationValue(LdapConfigProperty.USER_NAME_ATTRIBUTE);
   }
 
+  public String userSearchBase() {
+    return (String) configurationValue(LdapConfigProperty.USER_SEARCH_BASE);
+  }
+
+  public String groupObjectClass() {
+    return (String) configurationValue(LdapConfigProperty.GROUP_OBJECT_CLASS);
+  }
+
+  public String groupNameAttribute() {
+    return (String) configurationValue(LdapConfigProperty.GROUP_NAME_ATTRIBUTE);
+  }
+
+  public String groupMemberAttribute() {
+    return (String) configurationValue(LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE);
+  }
+
+  public String groupSearchBase() {
+    return (String) configurationValue(LdapConfigProperty.GROUP_SEARCH_BASE);
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
index 4667721..7efa3b7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
@@ -14,8 +14,11 @@
 
 package org.apache.ambari.server.ldap;
 
+import java.util.Set;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ldap.service.AmbariLdapException;
+import org.apache.directory.ldap.client.api.LdapConnection;
 
 /**
  * Collection of operations for validating ldap configuration.
@@ -26,27 +29,32 @@ public interface LdapConfigurationValidatorService {
   /**
    * Tests the connection based on the provided configuration.
    *
-   * @param configuration the ambari ldap configuration instance
+   * @param ldapConnection connection instance
+   * @param configuration  the ambari ldap configuration instance
    * @throws AmbariLdapException if the connection is not possible
    */
-  void checkConnection(AmbariLdapConfiguration configuration) throws AmbariLdapException;
+  void checkConnection(LdapConnection ldapConnection, AmbariLdapConfiguration configuration) throws AmbariLdapException;
+
 
   /**
-   * Checks whether the group related LDAP attributes in the configuration are correct.
+   * Implements LDAP user related configuration settings validation logic.
+   * Implementers communicate with the LDAP server (search, bind) to validate attributes in the provided configuration
+   * instance
    *
-   * @param configuration the configuration instance holding the available properties
-   * @throws AmbariException if the attributes are not valid
+   * @param ldapConnection connection instance used to connect to the LDAP server
+   * @param testUserName   the test username
+   * @param testPassword   the test password
+   * @param configuration  the available ldap configuration
+   * @return The DN of the found user entry
+   * @throws AmbariException if the connection couldn't be estabilisheds
    */
-  void checkGroupAttributes(AmbariLdapConfiguration configuration) throws AmbariException;
+  String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration configuration) throws AmbariLdapException;
 
   /**
-   * Tries to connect to the LDAP server with the given credentials.
-   * Primarily used for testing the user before performing other operations (eg. attribute detection)s
+   * Checks whether the group related LDAP attributes in the configuration are correct.
    *
-   * @param username      the username
-   * @param password      the password
-   * @param configuration the available ldap configuration
-   * @throws AmbariException if the connection couldn't be estabilished
+   * @throws AmbariException if the attributes are not valid
    */
-  void checkUserAttributes(String username, String password, AmbariLdapConfiguration configuration) throws AmbariException;
+  Set<String> checkGroupAttributes(LdapConnection ldapConnection, String userDn, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
index 625ce8b..545f220 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
@@ -17,7 +17,7 @@ package org.apache.ambari.server.ldap;
 
 import org.apache.ambari.server.ldap.service.AmbariLdapFacade;
 import org.apache.ambari.server.ldap.service.LdapFacade;
-import org.apache.ambari.server.ldap.service.ad.AdLdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.service.ad.DefaultLdapConfigurationValidatorService;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
@@ -30,7 +30,7 @@ public class LdapModule extends AbstractModule {
   @Override
   protected void configure() {
     bind(LdapFacade.class).to(AmbariLdapFacade.class);
-    bind(LdapConfigurationValidatorService.class).to(AdLdapConfigurationValidatorService.class);
+    bind(LdapConfigurationValidatorService.class).to(DefaultLdapConfigurationValidatorService.class);
 
     install(new FactoryModuleBuilder().build(LdapConfigurationFactory.class));
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
index abd028a..abb464b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
@@ -16,13 +16,14 @@
 package org.apache.ambari.server.ldap.service;
 
 import java.util.Map;
+import java.util.Set;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
 import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.apache.directory.ldap.client.api.LdapConnection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,17 +52,21 @@ public class AmbariLdapFacade implements LdapFacade {
   private LdapConfigurationValidatorService ldapConfigurationValidatorService;
 
   @Inject
+  private LdapConnectionService ldapConnectionService;
+
+  @Inject
   public AmbariLdapFacade() {
   }
 
   @Override
-  public void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException {
+  public void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
     try {
       LOGGER.info("Validating LDAP connection related configuration based on: {}", ambariLdapConfiguration);
-      ldapConfigurationValidatorService.checkConnection(ambariLdapConfiguration);
+      LdapConnection connection = ldapConnectionService.createLdapConnection(ambariLdapConfiguration);
+      ldapConfigurationValidatorService.checkConnection(connection, ambariLdapConfiguration);
     } catch (AmbariLdapException e) {
       LOGGER.error("Validating LDAP connection configuration failed", e);
-      throw new AmbariException("Validating LDAP connection configuration failed", e);
+      throw e;
     }
     LOGGER.info("Validating LDAP connection related configuration: SUCCESS");
   }
@@ -74,7 +79,7 @@ public class AmbariLdapFacade implements LdapFacade {
   }
 
   @Override
-  public void checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ldapConfiguration) throws AmbariException {
+  public void checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ldapConfiguration) throws AmbariLdapException {
     String userName = getTestUserNameFromParameters(parameters);
     String testUserPass = getTestUserPasswordFromParameters(parameters);
 
@@ -82,8 +87,14 @@ public class AmbariLdapFacade implements LdapFacade {
       throw new IllegalArgumentException("No test user available for testing LDAP attributes");
     }
 
-    LOGGER.info("Testing LDAP attributes with test user: {}", userName);
-    ldapConfigurationValidatorService.checkUserAttributes(userName, testUserPass, ldapConfiguration);
+    LdapConnection ldapConnection = ldapConnectionService.createLdapConnection(ldapConfiguration);
+
+    LOGGER.info("Testing LDAP user attributes with test user: {}", userName);
+    String userDn = ldapConfigurationValidatorService.checkUserAttributes(ldapConnection, userName, testUserPass, ldapConfiguration);
+
+    LOGGER.info("Testing LDAP group attributes with test user dn: {}", userDn);
+    Set<String> groups = ldapConfigurationValidatorService.checkGroupAttributes(ldapConnection, userDn, ldapConfiguration);
+
   }
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapConnectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapConnectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapConnectionService.java
new file mode 100644
index 0000000..50ee8ed
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapConnectionService.java
@@ -0,0 +1,35 @@
+/*
+ * 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.ldap.service;
+
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+
+/**
+ * Contract defining factory methods for creating LDAP connection instances.
+ * Implementers contain the logic of creating different connection instances and the afferent boilerplate code.
+ */
+public interface LdapConnectionService {
+
+  /**
+   * Creates an LdapConnection instance based on the provided configuration
+   *
+   * @param ambariLdapConfiguration configuration instance with information for creating the connection instance
+   * @return a set up LdapConnection instance
+   */
+  LdapNetworkConnection createLdapConnection(AmbariLdapConfiguration ambariLdapConfiguration);
+
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
index 38553f0..7bb1198 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
@@ -16,7 +16,6 @@ package org.apache.ambari.server.ldap.service;
 
 import java.util.Map;
 
-import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
 
 /**
@@ -29,9 +28,9 @@ public interface LdapFacade {
    * Tests the connection to the LDAP server based on the provided configuration.
    *
    * @param ambariLdapConfiguration the available ldap related configuration
-   * @throws AmbariException if the connection fails or other problems occur during the operation
+   * @throws AmbariLdapException if the connection fails or other problems occur during the operation
    */
-  void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException;
+  void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;
 
 
   /**
@@ -46,7 +45,7 @@ public interface LdapFacade {
    *
    * @param parameters              a map of property name and value pairs holding information to facilitate checking the attributes
    * @param ambariLdapConfiguration configutration instance with available attributes
-   * @throws AmbariException if the attribute checking fails
+   * @throws AmbariLdapException if the attribute checking fails
    */
-  void checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException;
+  void checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java
deleted file mode 100644
index 11e8655..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.ldap.service.ad;
-
-import java.io.IOException;
-import java.util.List;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
-import org.apache.ambari.server.ldap.service.AmbariLdapException;
-import org.apache.directory.api.ldap.model.cursor.EntryCursor;
-import org.apache.directory.api.ldap.model.cursor.SearchCursor;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.ldap.client.api.LdapConnectionConfig;
-import org.apache.directory.ldap.client.api.LdapNetworkConnection;
-import org.apache.directory.ldap.client.api.search.FilterBuilder;
-import org.apache.directory.shared.ldap.constants.SchemaConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Lists;
-
-/**
- * Implementation of the validation logic using the Apache Directory API.
- */
-@Singleton
-public class AdLdapConfigurationValidatorService implements LdapConfigurationValidatorService {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(AdLdapConfigurationValidatorService.class);
-
-  @Inject
-  private LdapConfigurationConverter ldapConfigurationConverter;
-
-  /**
-   * Facilitating the instantiation
-   */
-  @Inject
-  public AdLdapConfigurationValidatorService() {
-  }
-
-  @Override
-  public void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
-    try {
-      LOGGER.info("Testing the connection based on the configuration: {}", ambariLdapConfiguration);
-
-      LdapConnectionConfig connectionConfig = ldapConfigurationConverter.getLdapConnectionConfig(ambariLdapConfiguration);
-      LdapNetworkConnection connection = new LdapNetworkConnection(connectionConfig);
-
-      if (ambariLdapConfiguration.bindAnonimously()) {
-        LOGGER.debug("Binding anonimously ...");
-        connection.bind();
-      } else {
-        LOGGER.debug("Binding with manager DN and manager password ...");
-        connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
-      }
-
-      if (connection.isConnected()) {
-        LOGGER.info("Successfully connected to the LDAP server.");
-      }
-
-      connection.close();
-
-    } catch (Exception e) {
-      LOGGER.warn("Could not bind to the LDAP server base don the provided configuration ...");
-      throw new AmbariLdapException(e);
-    }
-  }
-
-
-  /**
-   * Checks the user attributes provided in the configuration instance by issuing a search for a (known) test user in the LDAP.
-   * Attributes are considered correct if there is at least one entry found.
-   *
-   * Invalid attributes are signaled by throwing an exception.
-   *
-   * @param username                the username
-   * @param password                the password
-   * @param ambariLdapConfiguration configuration instance holding ldap configuration details
-   * @throws AmbariException if the attributes are not valid or any errors occurs
-   */
-  @Override
-  public void checkUserAttributes(String username, String password, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException {
-    LdapNetworkConnection connection = null;
-    SearchCursor searchCursor = null;
-    try {
-      LOGGER.info("Checking user attributes for user {} r ...", username);
-
-      LdapConnectionConfig connectionConfig = ldapConfigurationConverter.getLdapConnectionConfig(ambariLdapConfiguration);
-      connection = new LdapNetworkConnection(connectionConfig);
-
-
-      if (!ambariLdapConfiguration.bindAnonimously()) {
-        LOGGER.debug("Anonimous binding not supported, binding with the manager detailas...");
-        connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
-      } else {
-        LOGGER.debug("Binding anonimously ...");
-        connection.bind();
-      }
-
-      if (!connection.isConnected()) {
-        LOGGER.error("Not connected to the LDAP server. Connection instance: {}", connection);
-        throw new IllegalStateException("The connection to the LDAP server is not alive");
-      }
-
-      // set up a filter based on the provided attributes
-      String filter = FilterBuilder.and(
-        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
-        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), username))
-        .toString();
-
-      LOGGER.info("Searching for the user: {} using the search filter: {}", username, filter);
-      EntryCursor entryCursor = connection.search(new Dn(ambariLdapConfiguration.baseDn()), filter, SearchScope.SUBTREE);
-
-      // collecting search result entries
-      List<Entry> users = Lists.newArrayList();
-      for (Entry entry : entryCursor) {
-        users.add(entry);
-      }
-
-      // there should be at least one user found
-      if (users.isEmpty()) {
-        String msg = String.format("There are no users found using the filter: [ %s ]. Try changing the attribute values", filter);
-        LOGGER.error(msg);
-        throw new Exception(msg);
-      }
-
-      LOGGER.info("Attibute validation succeeded. Filter: {}", filter);
-
-    } catch (Exception e) {
-
-      LOGGER.error("Error while checking user attributes.");
-      throw new AmbariException("Error while checking user attributes", e);
-
-    } finally {
-
-      LOGGER.debug("Closing the connection and searchresult ...");
-
-      if (null != searchCursor) {
-        searchCursor.close();
-      }
-
-      if (null != connection) {
-        try {
-          connection.close();
-        } catch (IOException e) {
-          LOGGER.error("Exception occurred while closing the connection", e);
-        }
-      }
-
-    }
-  }
-
-  @Override
-  public void checkGroupAttributes(AmbariLdapConfiguration configuration) throws AmbariException {
-
-  }
-
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java
new file mode 100644
index 0000000..838ef4c
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java
@@ -0,0 +1,232 @@
+/*
+ * 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.ldap.service.ad;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.service.AmbariLdapException;
+import org.apache.ambari.server.ldap.service.LdapConnectionService;
+import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.Response;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Implementation of the validation logic using the Apache Directory API.
+ */
+@Singleton
+public class DefaultLdapConfigurationValidatorService implements LdapConfigurationValidatorService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class);
+
+  @Inject
+  private LdapConnectionService ldapConnectionService;
+
+  /**
+   * Facilitating the instantiation
+   */
+  @Inject
+  public DefaultLdapConfigurationValidatorService() {
+  }
+
+  @Override
+  public void checkConnection(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    try {
+      bind(ambariLdapConfiguration, ldapConnection);
+    } catch (LdapException e) {
+      LOGGER.error("Could not connect to the LDAP server", e);
+      throw new AmbariLdapException(e);
+    }
+  }
+
+
+  /**
+   * Checks the user attributes provided in the configuration instance by issuing a search for a (known) test user in the LDAP.
+   * Attributes are considered correct if there is at least one entry found.
+   *
+   * Invalid attributes are signaled by throwing an exception.
+   *
+   * @param testUserName            the test username
+   * @param testPassword            the test password
+   * @param ambariLdapConfiguration configuration instance holding ldap configuration details
+   * @throws AmbariException if the attributes are not valid or any errors occurs
+   */
+  @Override
+  public String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    LdapNetworkConnection connection = null;
+    SearchCursor searchCursor = null;
+    String userDn = null;
+    try {
+      LOGGER.info("Checking user attributes for user {} r ...", testUserName);
+
+      // bind anonimously or with manager data
+      bind(ambariLdapConfiguration, connection);
+
+      // set up a filter based on the provided attributes
+      String filter = FilterBuilder.and(
+        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
+        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), testUserName))
+        .toString();
+
+      LOGGER.info("Searching for the user: {} using the search filter: {}", testUserName, filter);
+      EntryCursor entryCursor = connection.search(new Dn(ambariLdapConfiguration.userSearchBase()), filter, SearchScope.SUBTREE);
+
+      // collecting search result entries
+      List<Entry> users = Lists.newArrayList();
+      for (Entry entry : entryCursor) {
+        users.add(entry);
+        userDn = entry.getDn().getNormName();
+      }
+
+      // there should be at least one user found
+      if (users.isEmpty()) {
+        String msg = String.format("There are no users found using the filter: [ %s ]. Try changing the attribute values", filter);
+        LOGGER.error(msg);
+        throw new Exception(msg);
+      }
+
+      LOGGER.info("Attibute validation succeeded. Filter: {}", filter);
+
+    } catch (Exception e) {
+
+      LOGGER.error("User attributes validation failed.", e);
+      throw new AmbariLdapException(e.getMessage(), e);
+
+    } finally {
+      closeResources(connection, searchCursor);
+    }
+    return userDn;
+  }
+
+
+  @Override
+  public Set<String> checkGroupAttributes(LdapConnection ldapConnection, String userDn, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    SearchCursor searchCursor = null;
+    Set<Response> groupResponses = Sets.newHashSet();
+
+    try {
+      LOGGER.info("Checking group attributes for user dn {} ...", userDn);
+
+      bind(ambariLdapConfiguration, ldapConnection);
+
+      // set up a filter based on the provided attributes
+      String filter = FilterBuilder.and(
+        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.groupObjectClass()),
+        FilterBuilder.equal(ambariLdapConfiguration.groupMemberAttribute(), userDn)
+      ).toString();
+
+      LOGGER.info("Searching for the groups the user dn: {} is member of using the search filter: {}", userDn, filter);
+
+      // assemble a search request
+      SearchRequest searchRequest = new SearchRequestImpl();
+      searchRequest.setFilter(filter);
+      searchRequest.setBase(new Dn(ambariLdapConfiguration.groupSearchBase()));
+      searchRequest.setScope(SearchScope.SUBTREE);
+      searchRequest.addAttributes(ambariLdapConfiguration.groupMemberAttribute(), ambariLdapConfiguration.groupNameAttribute());
+
+      // perform the search
+      searchCursor = ldapConnection.search(searchRequest);
+
+      for (Response response : searchCursor) {
+        groupResponses.add(response);
+      }
+
+    } catch (Exception e) {
+
+      LOGGER.error("User attributes validation failed.", e);
+      throw new AmbariLdapException(e.getMessage(), e);
+
+    } finally {
+
+      closeResources(ldapConnection, searchCursor);
+
+    }
+
+    return processGroupResults(groupResponses, ambariLdapConfiguration);
+  }
+
+  private void bind(AmbariLdapConfiguration ambariLdapConfiguration, LdapConnection connection) throws LdapException {
+    LOGGER.info("Connecting to LDAP ....");
+    if (!ambariLdapConfiguration.bindAnonimously()) {
+      LOGGER.debug("Anonimous binding not supported, binding with the manager detailas...");
+      connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
+    } else {
+      LOGGER.debug("Binding anonimously ...");
+      connection.bind();
+    }
+
+    if (!connection.isConnected()) {
+      LOGGER.error("Not connected to the LDAP server. Connection instance: {}", connection);
+      throw new IllegalStateException("The connection to the LDAP server is not alive");
+    }
+    LOGGER.info("Connected to LDAP.");
+  }
+
+
+  private Set<String> processGroupResults(Set<Response> groupResponses, AmbariLdapConfiguration ambariLdapConfiguration) {
+    Set<String> groupStrSet = Sets.newHashSet();
+    for (Response response : groupResponses) {
+      Entry entry = ((SearchResultEntryDecorator) response).getEntry();
+      groupStrSet.add(entry.get(ambariLdapConfiguration.groupNameAttribute()).get().getString());
+    }
+
+    LOGGER.debug("Extracted group names from group search responses: {}", groupStrSet);
+    return groupStrSet;
+  }
+
+  private void closeResources(LdapConnection connection, SearchCursor searchCursor) {
+    LOGGER.debug("Housekeeping: closing the connection and the search cursor ...");
+
+    if (null != searchCursor) {
+      // this method is idempotent
+      searchCursor.close();
+    }
+
+    if (null != connection) {
+      try {
+        connection.close();
+      } catch (IOException e) {
+        LOGGER.error("Exception occurred while closing the connection", e);
+      }
+    }
+  }
+
+}
+
+
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java
new file mode 100644
index 0000000..b5559d9
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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.ldap.service.ad;
+
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.service.LdapConnectionService;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class DefaultLdapConnectionService implements LdapConnectionService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConnectionService.class);
+
+  @Override
+  public LdapNetworkConnection createLdapConnection(AmbariLdapConfiguration ambariLdapConfiguration) {
+    LOGGER.debug("Creating ldap connection instance from: {}", ambariLdapConfiguration);
+    return new LdapNetworkConnection(getLdapConnectionConfig(ambariLdapConfiguration));
+  }
+
+  private LdapConnectionConfig getLdapConnectionConfig(AmbariLdapConfiguration ambariAmbariLdapConfiguration) {
+    LOGGER.debug("Creating a configuration instance based on the ambari configuration: {}", ambariAmbariLdapConfiguration);
+
+    LdapConnectionConfig ldapConnectionConfig = new LdapConnectionConfig();
+    ldapConnectionConfig.setLdapHost(ambariAmbariLdapConfiguration.ldapServerHost());
+    ldapConnectionConfig.setLdapPort(ambariAmbariLdapConfiguration.ldapServerPort());
+    ldapConnectionConfig.setUseSsl(ambariAmbariLdapConfiguration.useSSL());
+
+    //todo set the other values as required
+    return ldapConnectionConfig;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java
deleted file mode 100644
index a8839f1..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.ldap.service.ad;
-
-import javax.inject.Singleton;
-
-import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.directory.ldap.client.api.LdapConnectionConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Converts between ambari specific ldap types and the 3rd party ldap library
- */
-@Singleton
-public class LdapConfigurationConverter {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(LdapConfigurationConverter.class);
-
-  /**
-   * Creates a {@link LdapConnectionConfig} instance based on the provided ambari specific configurations
-   *
-   * @param ambariAmbariLdapConfiguration
-   * @return
-   */
-  public LdapConnectionConfig getLdapConnectionConfig(AmbariLdapConfiguration ambariAmbariLdapConfiguration) {
-    LOGGER.debug("Creating a configuration instance based on the ambari configuration: {}", ambariAmbariLdapConfiguration);
-
-    LdapConnectionConfig ldapConnectionConfig = new LdapConnectionConfig();
-    ldapConnectionConfig.setLdapHost(ambariAmbariLdapConfiguration.ldapServerHost());
-    ldapConnectionConfig.setLdapPort(ambariAmbariLdapConfiguration.ldapServerPort());
-    ldapConnectionConfig.setUseSsl(ambariAmbariLdapConfiguration.useSSL());
-
-    //todo set the other values as required
-    return ldapConnectionConfig;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java
deleted file mode 100644
index 0f57099..0000000
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.ldap.service.ad;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.util.Map;
-
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
-import org.apache.directory.api.ldap.model.cursor.EntryCursor;
-import org.apache.directory.api.ldap.model.cursor.SearchCursor;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.message.Response;
-import org.apache.directory.api.ldap.model.message.SearchRequest;
-import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
-import org.apache.directory.api.ldap.model.message.SearchResultEntry;
-import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.ldap.client.api.LdapConnection;
-import org.apache.directory.ldap.client.api.LdapConnectionConfig;
-import org.apache.directory.ldap.client.api.LdapNetworkConnection;
-import org.apache.directory.ldap.client.api.search.FilterBuilder;
-import org.apache.directory.shared.ldap.constants.SchemaConstants;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
-
-public class AdLdapConfigurationValidatorServiceTest {
-  private static final Logger LOGGER = LoggerFactory.getLogger(AdLdapConfigurationValidatorService.class);
-  private static final String TEST_USER = "Jocika10";
-
-  LdapConfigurationValidatorService ldapConfigurationValidatorService = new AdLdapConfigurationValidatorService();
-
-
-  @Test
-  public void testCheckAttributes() throws Exception {
-
-    // WHEN
-    LdapConnectionConfig config = new LdapConnectionConfig();
-    config.setLdapHost("localhost");
-    config.setLdapPort(389);
-    LdapConnection connection = new LdapNetworkConnection(config);
-
-    // THEN
-    connection.anonymousBind();
-
-
-    EntryCursor cursor = connection.search("dc=dev,dc=local", "(objectclass=*)", SearchScope.ONELEVEL);
-
-    for (Entry entry : cursor) {
-      assertNotNull(entry);
-      System.out.println(entry);
-    }
-
-    cursor.close();
-
-  }
-
-  @Test
-  public void testCheckUserAttributes() throws Exception {
-    Map<String, Object> ldapPropsMap = Maps.newHashMap();
-
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), true);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "localhost");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=dev,dc=local");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
-
-    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
-
-
-    try {
-      LOGGER.info("Authenticating user {} against the LDAP server ...", TEST_USER);
-      LdapConfigurationConverter ldapConfigurationConverter = new LdapConfigurationConverter();
-
-      LdapConnectionConfig connectionConfig = ldapConfigurationConverter.getLdapConnectionConfig(ambariLdapConfiguration);
-      LdapNetworkConnection connection = new LdapNetworkConnection(connectionConfig);
-
-      String filter = FilterBuilder.and(
-        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
-        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), TEST_USER))
-        .toString();
-
-      SearchRequest searchRequest = new SearchRequestImpl();
-      searchRequest.setBase(new Dn(ambariLdapConfiguration.baseDn()));
-      searchRequest.setFilter(filter);
-      searchRequest.setScope(SearchScope.SUBTREE);
-
-      LOGGER.info("loking up user: {} based on the filtr: {}", TEST_USER, filter);
-
-      connection.bind();
-      SearchCursor searchCursor = connection.search(searchRequest);
-
-      while (searchCursor.next()) {
-        Response response = searchCursor.get();
-
-        // process the SearchResultEntry
-        if (response instanceof SearchResultEntry) {
-          Entry resultEntry = ((SearchResultEntry) response).getEntry();
-          System.out.println(resultEntry);
-        }
-      }
-
-      searchCursor.close();
-
-    } catch (Exception e) {
-      throw new AmbariException("Error during user authentication check", e);
-    }
-
-  }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/3ad545a4/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java
new file mode 100644
index 0000000..5c9d304
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.ldap.service.ad;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.service.LdapConnectionService;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.Response;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchResultEntry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class DefaultLdapConfigurationValidatorServiceTest {
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class);
+  private static final String TEST_USER = "einstein";
+
+  LdapConfigurationValidatorService ldapConfigurationValidatorService = new DefaultLdapConfigurationValidatorService();
+
+
+  @Test
+  public void testCheckAttributes() throws Exception {
+
+    // WHEN
+    LdapConnectionConfig config = new LdapConnectionConfig();
+    config.setLdapHost("localhost");
+    config.setLdapPort(389);
+    LdapConnection connection = new LdapNetworkConnection(config);
+
+    // THEN
+    connection.anonymousBind();
+
+
+    EntryCursor cursor = connection.search("dc=dev,dc=local", "(objectclass=*)", SearchScope.ONELEVEL);
+
+    for (Entry entry : cursor) {
+      assertNotNull(entry);
+      System.out.println(entry);
+    }
+
+    cursor.close();
+
+  }
+
+  @Test
+  public void testCheckUserAttributes() throws Exception {
+    Map<String, Object> ldapPropsMap = Maps.newHashMap();
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), false);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE.propertyName(), SchemaConstants.UNIQUE_MEMBER_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
+
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
+
+
+    try {
+      LOGGER.info("Authenticating user {} against the LDAP server ...", TEST_USER);
+      LdapConnectionService connectionService = new DefaultLdapConnectionService();
+      LdapNetworkConnection connection = connectionService.createLdapConnection(ambariLdapConfiguration);
+
+      String filter = FilterBuilder.and(
+        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
+        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), TEST_USER))
+        .toString();
+
+      SearchRequest searchRequest = new SearchRequestImpl();
+      searchRequest.setBase(new Dn(ambariLdapConfiguration.baseDn()));
+      searchRequest.setFilter(filter);
+      searchRequest.setScope(SearchScope.SUBTREE);
+
+      LOGGER.info("loking up user: {} based on the filtr: {}", TEST_USER, filter);
+
+      connection.bind();
+      SearchCursor searchCursor = connection.search(searchRequest);
+
+      while (searchCursor.next()) {
+        Response response = searchCursor.get();
+
+        // process the SearchResultEntry
+        if (response instanceof SearchResultEntry) {
+          Entry resultEntry = ((SearchResultEntry) response).getEntry();
+          System.out.println(resultEntry);
+        }
+      }
+
+      searchCursor.close();
+
+    } catch (Exception e) {
+      throw new AmbariException("Error during user authentication check", e);
+    }
+
+  }
+
+  @Test
+  public void testRetrieveGorupsForuser() throws Exception {
+    // GIVEN
+    Map<String, Object> ldapPropsMap = Maps.newHashMap();
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE.propertyName(), SchemaConstants.UNIQUE_MEMBER_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_SEARCH_BASE.propertyName(), "dc=example,dc=com");
+
+
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
+    LdapConnectionService connectionService = new DefaultLdapConnectionService();
+    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
+
+    ldapConfigurationValidatorService.checkGroupAttributes(ldapConnection, "uid=einstein,dc=example,dc=com", ambariLdapConfiguration);
+  }
+}
\ No newline at end of file


[19/38] ambari git commit: AMBARI-21941. Stack selection page does not load the HDP stacks [Intermittent] (ncole)

Posted by lp...@apache.org.
AMBARI-21941. Stack selection page does not load the HDP stacks [Intermittent] (ncole)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/16cc3a6e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/16cc3a6e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/16cc3a6e

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 16cc3a6ed6c5bd07c613433309322835e378d559
Parents: 2c10dc9
Author: Nate Cole <nc...@hortonworks.com>
Authored: Wed Sep 13 12:25:28 2017 -0400
Committer: Nate Cole <nc...@hortonworks.com>
Committed: Wed Sep 13 12:25:50 2017 -0400

----------------------------------------------------------------------
 .../ambari/server/stack/StackContext.java       | 109 ++++++++--
 .../apache/ambari/server/stack/StackModule.java |  48 +++-
 .../apache/ambari/server/state/StackInfo.java   |   1 -
 .../server/state/stack/RepoUrlInfoCallable.java | 217 +++++++++++++++++++
 .../server/state/stack/RepoVdfCallable.java     | 161 ++++++++++++++
 .../ComponentVersionCheckActionTest.java        |  14 --
 6 files changed, 510 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/16cc3a6e/ambari-server/src/main/java/org/apache/ambari/server/stack/StackContext.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackContext.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackContext.java
index db9d178..d430bb7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackContext.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackContext.java
@@ -18,18 +18,28 @@
 
 package org.apache.ambari.server.stack;
 
-import java.io.File;
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.ambari.server.metadata.ActionMetadata;
 import org.apache.ambari.server.orm.dao.MetainfoDAO;
-import org.apache.ambari.server.state.stack.LatestRepoCallable;
 import org.apache.ambari.server.state.stack.OsFamily;
+import org.apache.ambari.server.state.stack.RepoUrlInfoCallable;
+import org.apache.ambari.server.state.stack.RepoUrlInfoCallable.RepoUrlInfoResult;
+import org.apache.ambari.server.state.stack.RepoVdfCallable;
+import org.apache.commons.collections.MapUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Provides external functionality to the Stack framework.
@@ -46,15 +56,12 @@ public class StackContext {
   private ActionMetadata actionMetaData;
 
   /**
-   * Operating System families
-   */
-  private OsFamily osFamily;
-
-  /**
    * Executor used to get latest repo url's
    */
-  private LatestRepoQueryExecutor repoUpdateExecutor = new LatestRepoQueryExecutor();
+  private LatestRepoQueryExecutor repoUpdateExecutor;
 
+  private final static Logger LOG = LoggerFactory.getLogger(StackContext.class);
+  private static final int THREAD_COUNT = 5;
 
 
   /**
@@ -67,7 +74,7 @@ public class StackContext {
   public StackContext(MetainfoDAO metaInfoDAO, ActionMetadata actionMetaData, OsFamily osFamily) {
     this.metaInfoDAO = metaInfoDAO;
     this.actionMetaData = actionMetaData;
-    this.osFamily = osFamily;
+    repoUpdateExecutor = new LatestRepoQueryExecutor(osFamily);
   }
 
   /**
@@ -85,9 +92,8 @@ public class StackContext {
    * @param url    external repo information URL
    * @param stack  stack module
    */
-  public void registerRepoUpdateTask(String url, StackModule stack) {
-    repoUpdateExecutor.addTask(new LatestRepoCallable(url,
-        new File(stack.getStackDirectory().getRepoDir()), stack.getModuleInfo(), osFamily));
+  public void registerRepoUpdateTask(URI uri, StackModule stack) {
+    repoUpdateExecutor.addTask(uri, stack);
   }
 
   /**
@@ -115,16 +121,16 @@ public class StackContext {
     /**
      * Registered tasks
      */
-    private Collection<LatestRepoCallable> tasks = new ArrayList<>();
+    private Map<URI, RepoUrlInfoCallable> tasks = new HashMap<>();
 
     /**
      * Task futures
      */
-    Collection<Future<Void>> futures = new ArrayList<>();
+    Collection<Future<?>> futures = new ArrayList<>();
     /**
      * Underlying executor
      */
-    private ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
+    private ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT, new ThreadFactory() {
       @Override
       public Thread newThread(Runnable r) {
         return new Thread(r, "Stack Version Loading Thread");
@@ -132,22 +138,79 @@ public class StackContext {
     });
 
 
+    private OsFamily m_family;
+
+    private LatestRepoQueryExecutor(OsFamily family) {
+      m_family = family;
+    }
+
     /**
-     * Add a task.
-     *
-     * @param task task to be added
+     * @param uri
+     *          uri to load
+     * @param stackModule
+     *          the stack module
      */
-    public void addTask(LatestRepoCallable task) {
-      tasks.add(task);
+    public void addTask(URI uri, StackModule stackModule) {
+      RepoUrlInfoCallable callable = null;
+      if (tasks.containsKey(uri)) {
+        callable = tasks.get(uri);
+      } else {
+        callable = new RepoUrlInfoCallable(uri);
+        tasks.put(uri, callable);
+      }
+
+      callable.addStack(stackModule);
     }
 
     /**
      * Execute all tasks.
      */
     public void execute() {
-      for (LatestRepoCallable task : tasks) {
-        futures.add(executor.submit(task));
+
+      long l = System.nanoTime();
+      List<Future<Map<StackModule, RepoUrlInfoResult>>> results = new ArrayList<>();
+
+      // !!! first, load the *_urlinfo.json files and block for completion
+      try {
+        results = executor.invokeAll(tasks.values(), 2, TimeUnit.MINUTES);
+      } catch (InterruptedException e) {
+        LOG.warn("Could not load urlinfo as the executor was interrupted", e);
+        return;
+      } finally {
+        LOG.info("Loaded urlinfo in " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - l) + "ms");
+      }
+
+      List<Map<StackModule, RepoUrlInfoResult>> urlInfoResults = new ArrayList<>();
+      // !!! now load all the VDF _by version_ in a new thread.
+      for (Future<Map<StackModule, RepoUrlInfoResult>> future : results) {
+        try {
+          urlInfoResults.add(future.get());
+        } catch (Exception e) {
+          LOG.error("Could not load repo results", e.getCause());
+        }
       }
+
+      for (Map<StackModule, RepoUrlInfoResult> urlInfoResult : urlInfoResults) {
+        for (Entry<StackModule, RepoUrlInfoResult> entry : urlInfoResult.entrySet()) {
+          StackModule stackModule = entry.getKey();
+          RepoUrlInfoResult result = entry.getValue();
+
+          if (null != result) {
+            if (MapUtils.isNotEmpty(result.getManifest())) {
+              for (Entry<String, Map<String, URI>> manifestEntry : result.getManifest().entrySet()) {
+                futures.add(executor.submit(new RepoVdfCallable(stackModule, manifestEntry.getKey(),
+                    manifestEntry.getValue(), m_family)));
+              }
+            }
+
+            if (MapUtils.isNotEmpty(result.getLatestVdf())) {
+             futures.add(executor.submit(
+                 new RepoVdfCallable(stackModule, result.getLatestVdf(), m_family)));
+            }
+          }
+        }
+      }
+
       executor.shutdown();
     }
 
@@ -157,7 +220,7 @@ public class StackContext {
      * @return true if all tasks have completed; false otherwise
      */
     public boolean hasCompleted() {
-      for (Future<Void> f : futures) {
+      for (Future<?> f : futures) {
         if (! f.isDone()) {
           return false;
         }

http://git-wip-us.apache.org/repos/asf/ambari/blob/16cc3a6e/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java
index 3688727..6dc2b93 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java
@@ -19,6 +19,8 @@
 package org.apache.ambari.server.stack;
 
 import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -1143,10 +1145,52 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
     stackInfo.getRepositories().addAll(serviceRepos);
 
     if (null != rxml && null != rxml.getLatestURI() && stackRepos.size() > 0) {
-      stackContext.registerRepoUpdateTask(rxml.getLatestURI(), this);
+      registerRepoUpdateTask(rxml);
     }
   }
 
+  private void registerRepoUpdateTask(RepositoryXml rxml) {
+    String latest = rxml.getLatestURI();
+    if (StringUtils.isBlank(latest)) {
+      return;
+    }
+
+    URI uri = getURI(this, latest);
+
+    if (null == uri) {
+      LOG.warn("Could not determine how to load stack {}-{} latest definition for {}",
+          stackInfo.getName(), stackInfo.getVersion(), latest);
+      return;
+    }
+
+    stackContext.registerRepoUpdateTask(uri, this);
+  }
+
+  /**
+   * @param module
+   *          the stack module
+   * @param uriString
+   *          the uri string
+   * @return  a repo URI, even if it is relative-file based
+   */
+  public static URI getURI(StackModule module, String uriString) {
+
+    URI uri = null;
+    if (uriString.startsWith("http")) {
+      try {
+        uri = new URI(uriString);
+      } catch (URISyntaxException e) {
+        // should be logged later
+      }
+    } else if ('.' == uriString.charAt(0)) {
+      uri = new File(module.getStackDirectory().getRepoDir(), uriString).toURI();
+    } else {
+      uri = new File(uriString).toURI();
+    }
+
+    return uri;
+  }
+
   /**
    * Gets the service repos with duplicates filtered out. A service repo is considered duplicate if:
    * <ul>
@@ -1233,7 +1277,7 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
         if (null != serviceRepoXml) {
           repos.addAll(serviceRepoXml.getRepositories());
           if (null != serviceRepoXml.getLatestURI()) {
-            stackContext.registerRepoUpdateTask(serviceRepoXml.getLatestURI(), this);
+            registerRepoUpdateTask(serviceRepoXml);
           }
         }
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/16cc3a6e/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
index 6184b94..a3886ab 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
@@ -33,7 +33,6 @@ import org.apache.ambari.server.controller.StackVersionResponse;
 import org.apache.ambari.server.stack.Validable;
 import org.apache.ambari.server.state.repository.VersionDefinitionXml;
 import org.apache.ambari.server.state.stack.ConfigUpgradePack;
-import org.apache.ambari.server.state.stack.LatestRepoCallable;
 import org.apache.ambari.server.state.stack.RepositoryXml;
 import org.apache.ambari.server.state.stack.StackRoleCommandOrder;
 import org.apache.ambari.server.state.stack.UpgradePack;

http://git-wip-us.apache.org/repos/asf/ambari/blob/16cc3a6e/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoUrlInfoCallable.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoUrlInfoCallable.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoUrlInfoCallable.java
new file mode 100644
index 0000000..ec1071e
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoUrlInfoCallable.java
@@ -0,0 +1,217 @@
+/**
+ * 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.state.stack;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.ambari.server.controller.internal.URLStreamProvider;
+import org.apache.ambari.server.stack.StackModule;
+import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.stack.RepoUrlInfoCallable.RepoUrlInfoResult;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ * Encapsulates the work to resolve the latest repo information for a stack.
+ * This class must be used AFTER the stack has created its owned repositories.
+ */
+public class RepoUrlInfoCallable implements Callable<Map<StackModule, RepoUrlInfoResult>> {
+  private static final int LOOKUP_CONNECTION_TIMEOUT = 2000;
+  private static final int LOOKUP_READ_TIMEOUT = 3000;
+
+  private final static Logger LOG = LoggerFactory.getLogger(RepoUrlInfoCallable.class);
+
+  private URI m_uri = null;
+  private Set<StackModule> m_stacks = new HashSet<>();
+
+  public RepoUrlInfoCallable(URI uri) {
+    m_uri = uri;
+  }
+
+  public void addStack(StackModule stackModule) {
+    m_stacks.add(stackModule);
+  }
+
+  @Override
+  public Map<StackModule, RepoUrlInfoResult> call() throws Exception {
+
+    Type type = new TypeToken<Map<String, Map<String, Object>>>(){}.getType();
+    Gson gson = new Gson();
+
+    Map<String, Map<String, Object>> latestUrlMap = null;
+
+    Set<String> ids = new HashSet<>();
+    ids.addAll(Collections2.transform(m_stacks, new Function<StackModule, String>() {
+      @Override
+      public String apply(StackModule input) {
+        // TODO Auto-generated method stub
+        return new StackId(input.getModuleInfo()).toString();
+      }
+    }));
+
+    String stackIds = StringUtils.join(ids, ',');
+
+    Long time = System.nanoTime();
+
+    try {
+      if (m_uri.getScheme().startsWith("http")) {
+        URLStreamProvider streamProvider = new URLStreamProvider(
+            LOOKUP_CONNECTION_TIMEOUT, LOOKUP_READ_TIMEOUT,
+            null, null, null);
+
+        LOG.info("Loading latest URL info from {} for stacks {}", m_uri, stackIds);
+
+        latestUrlMap = gson.fromJson(new InputStreamReader(
+            streamProvider.readFrom(m_uri.toString())), type);
+      } else {
+        File jsonFile = new File(m_uri);
+
+        if (jsonFile.exists()) {
+          LOG.info("Loading latest URL info from file {} for stacks {}", m_uri, stackIds);
+          latestUrlMap = gson.fromJson(new FileReader(jsonFile), type);
+        }
+      }
+    } catch (Exception e) {
+      LOG.info("Could not load the URI from {}, stack defaults will be used", m_uri);
+      throw e;
+    } finally {
+      LOG.info("Loaded URI {} for stacks {} in {}ms", m_uri, stackIds,
+          TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - time));
+    }
+
+    Map<StackModule, RepoUrlInfoResult> result = new HashMap<>();
+
+    if (null == latestUrlMap) {
+      LOG.error("Could not load latest data for URI {} and stacks {}", m_uri, stackIds);
+      return result;
+    }
+
+    for (StackModule stackModule : m_stacks) {
+      StackId stackId = new StackId(stackModule.getModuleInfo());
+
+      Map<String, Object> map = latestUrlMap.get(stackId.toString());
+
+      if (null == map) {
+        continue;
+      }
+
+      RepoUrlInfoResult res = new RepoUrlInfoResult();
+
+      if (map.containsKey("manifests")) {
+        // versionMap is laid out like [version -> [os -> VDF uri]]
+        @SuppressWarnings("unchecked")
+        Map<String, Map<String, String>> versionMap = (Map<String, Map<String, String>>) map.get("manifests");
+
+        for (Entry<String, Map<String, String>> versionEntry : versionMap.entrySet()) {
+          String version = versionEntry.getKey();
+          Map<String, URI> resolvedOsMap = resolveOsMap(stackModule, versionEntry.getValue());
+
+          res.addVersion(version, resolvedOsMap);
+        }
+      }
+
+
+      if (map.containsKey("latest-vdf")) {
+        @SuppressWarnings("unchecked")
+        Map<String, String> osMap = (Map<String, String>) map.get("latest-vdf");
+
+        Map<String, URI> resolvedOsMap = resolveOsMap(stackModule, osMap);
+
+        res.setLatest(resolvedOsMap);
+      }
+
+      result.put(stackModule, res);
+    }
+
+
+    return result;
+
+  }
+
+  private Map<String, URI> resolveOsMap(StackModule stackModule, Map<String, String> osMap) {
+
+    Map<String, URI> resolved = new HashMap<>();
+
+    for (Entry<String, String> osEntry : osMap.entrySet()) {
+
+      String uriString = osEntry.getValue();
+
+      URI uri = StackModule.getURI(stackModule, uriString);
+
+      if (null == uri) {
+        LOG.warn("Could not resolve URI {}", uriString);
+      } else {
+        resolved.put(osEntry.getKey(), uri);
+      }
+    }
+
+    return resolved;
+  }
+
+
+  /**
+   * Stores the results saved per StackModule
+   */
+  public static class RepoUrlInfoResult {
+
+    private Map<String, Map<String, URI>> versions = new HashMap<>();
+    private Map<String, URI> latestVdf = new HashMap<>();
+
+    private void addVersion(String version, Map<String, URI> vdfMap) {
+      versions.put(version, vdfMap);
+    }
+
+    private void setLatest(Map<String, URI> latestMap) {
+      latestVdf = latestMap;
+    }
+
+    /**
+     * Each version entry here should be loaded in it's entirety in a new thread
+     */
+    public Map<String, Map<String, URI>> getManifest() {
+
+      return versions;
+    }
+
+    /**
+     * @return the latest vdf map
+     */
+    public Map<String, URI> getLatestVdf() {
+
+      return latestVdf;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/16cc3a6e/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoVdfCallable.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoVdfCallable.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoVdfCallable.java
new file mode 100644
index 0000000..81657a7
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoVdfCallable.java
@@ -0,0 +1,161 @@
+/**
+ * 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.state.stack;
+
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.apache.ambari.server.stack.StackModule;
+import org.apache.ambari.server.state.RepositoryInfo;
+import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.StackInfo;
+import org.apache.ambari.server.state.repository.VersionDefinitionXml;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Encapsulates the work to resolve the latest repo information for a stack.
+ * This class must be used AFTER the stack has created its owned repositories.
+ */
+public class RepoVdfCallable implements Callable<Void> {
+
+  private final static Logger LOG = LoggerFactory.getLogger(RepoVdfCallable.class);
+
+  // !!! these are required for this callable to work
+  private final StackInfo m_stack;
+  private final OsFamily m_family;
+  private final Map<String, URI> m_vdfMap;
+
+  // !!! determines if this is for manifests or latest-vdf
+  private String m_version;
+
+  public RepoVdfCallable(StackModule stackModule,
+      String version, Map<String, URI> vdfOsMap, OsFamily os_family) {
+    m_stack = stackModule.getModuleInfo();
+    m_family = os_family;
+    m_version = version;
+    m_vdfMap = vdfOsMap;
+  }
+
+  public RepoVdfCallable(StackModule stackModule,
+      Map<String, URI> vdfOsMap, OsFamily os_family) {
+    m_stack = stackModule.getModuleInfo();
+    m_family = os_family;
+    m_version = null;
+    m_vdfMap = vdfOsMap;
+  }
+
+  @Override
+  public Void call() throws Exception {
+    if (MapUtils.isEmpty(m_vdfMap)) {
+      return null;
+    }
+
+    boolean forLatest = (null == m_version);
+
+    StackId stackId = new StackId(m_stack);
+
+    VersionDefinitionXml xml = mergeDefinitions(stackId, m_version, m_vdfMap);
+
+    if (null == xml) {
+      return null;
+    }
+
+    if (forLatest) {
+      xml.setStackDefault(true);
+      m_stack.setLatestVersionDefinition(xml);
+    } else {
+      m_stack.addVersionDefinition(m_version, xml);
+    }
+
+    return null;
+  }
+
+  /**
+   * Merges definitions loaded from the common file
+   * @param stackId the stack id
+   * @param version the version string
+   * @param osMap   the map containing all the VDF for an OS
+   * @return the merged version definition
+   * @throws Exception
+   */
+  private VersionDefinitionXml mergeDefinitions(StackId stackId, String version,
+      Map<String, URI> osMap) throws Exception {
+
+    Set<String> oses = new HashSet<>();
+    for (RepositoryInfo ri : m_stack.getRepositories()) {
+      if (null != m_family.find(ri.getOsType())) {
+        oses.add(m_family.find(ri.getOsType()));
+      }
+    }
+
+    VersionDefinitionXml.Merger merger = new VersionDefinitionXml.Merger();
+
+    for (Entry<String, URI> versionEntry : osMap.entrySet()) {
+
+      String osFamily = m_family.find(versionEntry.getKey());
+      URI uri = versionEntry.getValue();
+
+      // !!! check for aliases.  Moving this to OsFamily could result in incorrect behavior
+      if (null == osFamily) {
+        String alias = m_family.getAliases().get(versionEntry.getKey());
+        if (null != alias) {
+          osFamily = m_family.find(alias);
+        }
+      }
+
+      // !!! if the family is not known OR not part of the stack, skip
+      if (null == osFamily || !oses.contains(osFamily)) {
+        LOG.info("Stack {} cannot resolve OS {} to the supported ones: {}. Family: {}",
+            stackId, versionEntry.getKey(), StringUtils.join(oses, ','), osFamily);
+        continue;
+      }
+
+      try {
+        VersionDefinitionXml xml = timedVDFLoad(uri);
+
+        version = (null == version) ? xml.release.version : version;
+        merger.add(version, xml);
+
+      } catch (Exception e) {
+        LOG.warn("Could not load version definition for {} identified by {}. {}",
+            stackId, uri.toString(), e.getMessage(), e);
+      }
+    }
+
+    return merger.merge();
+  }
+
+  private VersionDefinitionXml timedVDFLoad(URI uri) throws Exception {
+    long time = System.currentTimeMillis();
+
+    try {
+      return VersionDefinitionXml.load(uri.toURL());
+    } finally {
+      LOG.debug("Loaded VDF {} in {}ms", uri, System.currentTimeMillis() - time);
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/16cc3a6e/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckActionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckActionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckActionTest.java
index d07ac15..9f87312 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckActionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckActionTest.java
@@ -36,7 +36,6 @@ import org.apache.ambari.server.actionmanager.HostRoleCommandFactory;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.agent.CommandReport;
 import org.apache.ambari.server.agent.ExecutionCommand;
-import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.orm.OrmTestHelper;
@@ -56,7 +55,6 @@ import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ConfigFactory;
 import org.apache.ambari.server.state.Host;
-import org.apache.ambari.server.state.RepositoryInfo;
 import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
@@ -308,12 +306,6 @@ public class ComponentVersionCheckActionTest {
 
     makeUpgradeCluster(sourceStack, sourceRepo, targetStack, targetRepo);
 
-    // Verify the repo before calling Finalize
-    AmbariMetaInfo metaInfo = m_injector.getInstance(AmbariMetaInfo.class);
-
-    RepositoryInfo repo = metaInfo.getRepository(sourceStack.getStackName(), sourceStack.getStackVersion(), "redhat6", sourceStack.getStackId());
-    assertEquals(HDP_211_CENTOS6_REPO_URL, repo.getBaseUrl());
-
     // Finalize the upgrade
     Map<String, String> commandParams = new HashMap<>();
     ExecutionCommand executionCommand = new ExecutionCommand();
@@ -470,12 +462,6 @@ public class ComponentVersionCheckActionTest {
     sch = createNewServiceComponentHost(cluster, "ZOOKEEPER", "ZOOKEEPER_SERVER", "h1");
     sch.setVersion(HDP_2_1_1_1);
 
-    // Verify the repo before calling Finalize
-    AmbariMetaInfo metaInfo = m_injector.getInstance(AmbariMetaInfo.class);
-
-    RepositoryInfo repo = metaInfo.getRepository(sourceStack.getStackName(), sourceStack.getStackVersion(), "redhat6", sourceStack.getStackId());
-    assertEquals(HDP_211_CENTOS6_REPO_URL, repo.getBaseUrl());
-
     // Finalize the upgrade
     Map<String, String> commandParams = new HashMap<>();
     ExecutionCommand executionCommand = new ExecutionCommand();


[18/38] ambari git commit: AMBARI-21949. Stacks And Versions Page Displays Wrong Version For Service (alexantonenko)

Posted by lp...@apache.org.
AMBARI-21949. Stacks And Versions Page Displays Wrong Version For Service (alexantonenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2c10dc92
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2c10dc92
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2c10dc92

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 2c10dc92047017771e6fca8d9d76d6d6b00df372
Parents: 153d0da
Author: Alex Antonenko <aa...@hortonworks.com>
Authored: Wed Sep 13 18:40:22 2017 +0300
Committer: Alex Antonenko <aa...@hortonworks.com>
Committed: Wed Sep 13 18:40:22 2017 +0300

----------------------------------------------------------------------
 .../app/controllers/global/update_controller.js |  2 +-
 ambari-web/app/mappers/service_mapper.js        |  6 +++--
 .../app/mappers/service_metrics_mapper.js       |  3 ++-
 ambari-web/app/models/service.js                |  1 +
 ambari-web/app/styles/stack_versions.less       |  9 -------
 .../upgrade_version_column_view.js              | 13 +++-------
 .../upgrade_version_column_view_test.js         | 27 +++++++++++++++++---
 7 files changed, 35 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/2c10dc92/ambari-web/app/controllers/global/update_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/global/update_controller.js b/ambari-web/app/controllers/global/update_controller.js
index 8a3f984..d33c5f1 100644
--- a/ambari-web/app/controllers/global/update_controller.js
+++ b/ambari-web/app/controllers/global/update_controller.js
@@ -520,7 +520,7 @@ App.UpdateController = Em.Controller.extend({
 
   updateServices: function (callback) {
     var testUrl = '/data/services/HDP2/services.json';
-    var componentConfigUrl = this.getUrl(testUrl, '/services?fields=ServiceInfo/state,ServiceInfo/maintenance_state,components/ServiceComponentInfo/component_name&minimal_response=true');
+    var componentConfigUrl = this.getUrl(testUrl, '/services?fields=ServiceInfo/state,ServiceInfo/maintenance_state,ServiceInfo/desired_repository_version_id,components/ServiceComponentInfo/component_name&minimal_response=true');
     App.HttpClient.get(componentConfigUrl, App.serviceMapper, {
       complete: callback
     });

http://git-wip-us.apache.org/repos/asf/ambari/blob/2c10dc92/ambari-web/app/mappers/service_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/service_mapper.js b/ambari-web/app/mappers/service_mapper.js
index 3523379..24130dd 100644
--- a/ambari-web/app/mappers/service_mapper.js
+++ b/ambari-web/app/mappers/service_mapper.js
@@ -23,7 +23,8 @@ App.serviceMapper = App.QuickDataMapper.create({
   config: {
     id: 'ServiceInfo.service_name',
     service_name: 'ServiceInfo.service_name',
-    work_status: 'ServiceInfo.state'
+    work_status: 'ServiceInfo.state',
+    desired_repository_version_id: 'ServiceInfo.desired_repository_version_id'
   },
   initialAppLoad: false,
   passiveStateMap: {},
@@ -41,7 +42,8 @@ App.serviceMapper = App.QuickDataMapper.create({
         var serviceData = {
           ServiceInfo: {
             service_name: service.ServiceInfo.service_name,
-            state: service.ServiceInfo.state
+            state: service.ServiceInfo.state,
+            desired_repository_version_id: service.ServiceInfo.desired_repository_version_id
           },
           host_components: [],
           components: []

http://git-wip-us.apache.org/repos/asf/ambari/blob/2c10dc92/ambari-web/app/mappers/service_metrics_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/service_metrics_mapper.js b/ambari-web/app/mappers/service_metrics_mapper.js
index 87b6149..9f79905 100644
--- a/ambari-web/app/mappers/service_metrics_mapper.js
+++ b/ambari-web/app/mappers/service_metrics_mapper.js
@@ -36,7 +36,8 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
     installed_clients: 'installed_clients',
     client_components: 'client_components',
     slave_components: 'slave_components',
-    master_components: 'master_components'
+    master_components: 'master_components',
+    desired_repository_version_id: 'ServiceInfo.desired_repository_version_id'
   },
   hdfsConfig: {
     version: 'nameNodeComponent.host_components[0].metrics.dfs.namenode.Version',

http://git-wip-us.apache.org/repos/asf/ambari/blob/2c10dc92/ambari-web/app/models/service.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/service.js b/ambari-web/app/models/service.js
index 70ae917..563add8 100644
--- a/ambari-web/app/models/service.js
+++ b/ambari-web/app/models/service.js
@@ -30,6 +30,7 @@ App.Service = DS.Model.extend({
   quickLinks: DS.hasMany('App.QuickLinks'),  // mapped in app/mappers/service_metrics_mapper.js method - mapQuickLinks
   hostComponents: DS.hasMany('App.HostComponent'),
   serviceConfigsTemplate: App.config.get('preDefinedServiceConfigs'),
+  desiredRepositoryVersionId: DS.attr('number'),
   /**
    * used by services("OOZIE", "ZOOKEEPER", "HIVE", "MAPREDUCE2", "TEZ", "SQOOP", "PIG","FALCON")
    * that have only client components

http://git-wip-us.apache.org/repos/asf/ambari/blob/2c10dc92/ambari-web/app/styles/stack_versions.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/stack_versions.less b/ambari-web/app/styles/stack_versions.less
index e8afaf4..804bb4d 100644
--- a/ambari-web/app/styles/stack_versions.less
+++ b/ambari-web/app/styles/stack_versions.less
@@ -358,15 +358,6 @@
       }
     }
   }
-  div.current-version-box.version-column {
-    .services-section{
-      .service-version-info {
-        span.label {
-          background-color: #468847;
-        }
-      }
-    }
-  }
   div.version-column {
     .not-upgradable {
       padding-left: 10px;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2c10dc92/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_column_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_column_view.js b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_column_view.js
index b5933b9..0ae8252 100644
--- a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_column_view.js
+++ b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_column_view.js
@@ -69,24 +69,17 @@ App.UpgradeVersionColumnView = App.UpgradeVersionBoxView.extend({
    * @returns {boolean}
    */
   isStackServiceAvailable: function(stackService) {
+    var self = this;
     if (!stackService) {
       return false;
     }
     if ( this.get('content.isCurrent') ){
-      // if version is current, check whether this service is available and the version itself is the newest version of all versions that contain the same service
-      var serviceWithHigherVersion =  App.RepositoryVersion.find().filterProperty('isCurrent').find(function ( version ) {
-        var service = version.get('stackServices').toArray().find( function (service) {
-          return service.get('name') === stackService.get('name') && service.get('isAvailable')
-        });
-        return Boolean(service && stringUtils.compareVersions(version.get('repositoryVersion'), this.get('content.repositoryVersion')) === 1);
-      }, this);
-      return stackService.get('isAvailable') && !serviceWithHigherVersion;
+      var originalService = App.Service.find(stackService.get('name'));
+      return stackService.get('isAvailable') && originalService.get('desiredRepositoryVersionId') === this.get('content.id');
     }
     else{
       return stackService.get('isAvailable')
     }
-
-
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/2c10dc92/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_column_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_column_view_test.js b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_column_view_test.js
index a7cb395..1c68fa3 100644
--- a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_column_view_test.js
+++ b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_column_view_test.js
@@ -22,8 +22,23 @@ require('views/main/admin/stack_upgrade/upgrade_version_column_view');
 
 describe('App.UpgradeVersionColumnView', function () {
   var view =  App.UpgradeVersionColumnView.create({});
+  var services = [
+    Em.Object.create({
+      id: 'zk',
+      desiredRepositoryVersionId: 1
+    }),
+    Em.Object.create({
+      id: 'storm',
+      desiredRepositoryVersionId: 2
+    }),
+    Em.Object.create({
+      id: 'hdfs',
+      desiredRepositoryVersionId: 1
+    })
+  ];
   var versions = [
     Em.Object.create({
+      id: 1,
       status: "CURRENT",
       repositoryVersion: "2.3.1.1",
       stackVersionType: 'HDP',
@@ -45,6 +60,7 @@ describe('App.UpgradeVersionColumnView', function () {
       ]
     }),
     Em.Object.create({
+      id: 2,
       status: "CURRENT",
       repositoryVersion: "2.2.0.1",
       stackVersionType: 'HDP',
@@ -66,6 +82,7 @@ describe('App.UpgradeVersionColumnView', function () {
       ]
     }),
     Em.Object.create({
+      id: 3,
       status: "INSTALLED",
       repositoryVersion: "2.0.2.1",
       stackVersionType: 'HCP',
@@ -92,10 +109,14 @@ describe('App.UpgradeVersionColumnView', function () {
   
   describe("#isStackServiceAvailable", function () {
     beforeEach(function() {
-      sinon.stub(App.RepositoryVersion, 'find').returns(versions);
+      sinon.stub(App.Service, 'find', function (id) {
+        return services.find(function (service) {
+          return id === service.get('id');
+        })
+      })
     });
     afterEach(function() {
-      App.RepositoryVersion.find.restore();
+      App.Service.find.restore();
     });
     it('Current upgrade with invalid service', function () {
       view.set('content', versions[0]);
@@ -122,4 +143,4 @@ describe('App.UpgradeVersionColumnView', function () {
       expect(view.isStackServiceAvailable(versions[1].get('stackServices')[1])).to.be.true;
     });
   });
-});
\ No newline at end of file
+});


[33/38] ambari git commit: AMBARI-21307 AddedLDAP configuration provider for loading and maintaining the LDAP configuration in the application

Posted by lp...@apache.org.
AMBARI-21307 AddedLDAP configuration provider for loading and maintaining the LDAP configuration in the application


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/37f90058
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/37f90058
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/37f90058

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 37f9005829f1d18c6dc99a0dc04829f4c1946bdd
Parents: fa7d7ec
Author: lpuskas <lp...@apache.org>
Authored: Tue Aug 29 14:55:09 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:31 2017 +0200

----------------------------------------------------------------------
 .../services/ldap/LdapConfigurationService.java |   1 +
 .../AmbariConfigurationResourceProvider.java    |  35 +++++-
 .../ambari/server/events/AmbariEvent.java       |  11 +-
 .../events/AmbariLdapConfigChangedEvent.java    |  37 ++++++
 .../server/ldap/LdapConfigurationFactory.java   |   2 +-
 .../apache/ambari/server/ldap/LdapModule.java   |   3 +
 .../AmbariLdapConfigurationProvider.java        | 114 +++++++++++++++++++
 .../server/ldap/service/AmbariLdapFacade.java   |   7 +-
 .../server/orm/dao/AmbariConfigurationDAO.java  |  48 ++++++++
 .../orm/entities/AmbariConfigurationEntity.java |   4 +-
 .../DefaultLdapConfigurationServiceTest.java    |  10 +-
 11 files changed, 260 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
index fc6bd41..1b8427b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
@@ -82,6 +82,7 @@ public class LdapConfigurationService extends AmbariConfigurationService {
   @Produces(MediaType.APPLICATION_JSON)
   public Response validateConfiguration(LdapConfigurationRequest ldapConfigurationRequest) {
 
+    // check if the user is authorized to perform the operation
     authorize();
 
     Set<String> groups = Sets.newHashSet();

http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/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
index 2302d8b..4f4cc70 100644
--- 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
@@ -35,6 +35,9 @@ 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.events.AmbariEvent;
+import org.apache.ambari.server.events.AmbariLdapConfigChangedEvent;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
 import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
 import org.apache.ambari.server.orm.entities.ConfigurationBaseEntity;
@@ -113,6 +116,10 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
   @Inject
   private AmbariConfigurationDAO ambariConfigurationDAO;
 
+  @Inject
+  private AmbariEventPublisher publisher;
+
+
   private Gson gson;
 
   @AssistedInject
@@ -142,7 +149,18 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
     }
 
     LOGGER.info("Persisting new ambari configuration: {} ", ambariConfigurationEntity);
-    ambariConfigurationDAO.create(ambariConfigurationEntity);
+
+    try {
+      ambariConfigurationDAO.create(ambariConfigurationEntity);
+    } catch (Exception e) {
+      LOGGER.error("Failed to create resource", e);
+      throw new ResourceAlreadyExistsException(e.getMessage());
+    }
+
+    // todo filter by configuration type
+    // notify subscribers about the configuration changes
+    publisher.publish(new AmbariLdapConfigChangedEvent(AmbariEvent.AmbariEventType.LDAP_CONFIG_CHANGED,
+      ambariConfigurationEntity.getId()));
 
     return getRequestStatus(null);
   }
@@ -183,6 +201,10 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
 
     }
 
+    // notify subscribers about the configuration changes
+    publisher.publish(new AmbariLdapConfigChangedEvent(AmbariEvent.AmbariEventType.LDAP_CONFIG_CHANGED, idFromRequest));
+
+
     return getRequestStatus(null);
 
   }
@@ -209,11 +231,15 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
       persistedEntity.getConfigurationBaseEntity().setConfigurationAttributes(entityFromRequest.getConfigurationBaseEntity().getConfigurationAttributes());
 
 
-      ambariConfigurationDAO.create(persistedEntity);
+      ambariConfigurationDAO.update(persistedEntity);
     } catch (AmbariException e) {
       throw new NoSuchParentResourceException(e.getMessage());
     }
 
+    publisher.publish(new AmbariLdapConfigChangedEvent(AmbariEvent.AmbariEventType.LDAP_CONFIG_CHANGED,
+      persistedEntity.getId()));
+
+
     return getRequestStatus(null);
 
   }
@@ -251,6 +277,11 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
       throw new AmbariException("There must be only one resource specified in the request");
     }
 
+    // the configuration type must be set
+    if (getValueFromResourceProperties(ResourcePropertyId.TYPE, resourcePropertiesSet.iterator().next()) == null) {
+      throw new AmbariException("The configuration type must be set");
+    }
+
 
     for (ResourcePropertyId resourcePropertyId : ResourcePropertyId.values()) {
       Object requestValue = getValueFromResourceProperties(resourcePropertyId, resourcePropertiesSet.iterator().next());

http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
index 9a5ee79..0f9ff52 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
@@ -140,7 +140,13 @@ public abstract class AmbariEvent {
     /**
      * Local user has been created.
      */
-    USER_CREATED;
+    USER_CREATED,
+
+    /**
+     * LDAP config changed event;
+     */
+    LDAP_CONFIG_CHANGED;
+
   }
 
   /**
@@ -151,8 +157,7 @@ public abstract class AmbariEvent {
   /**
    * Constructor.
    *
-   * @param eventType
-   *          the type of event (not {@code null}).
+   * @param eventType the type of event (not {@code null}).
    */
   public AmbariEvent(AmbariEventType eventType) {
     m_eventType = eventType;

http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java
new file mode 100644
index 0000000..48799d7
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java
@@ -0,0 +1,37 @@
+/*
+ * 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.events;
+
+/**
+ * Event signaling the creation or changing of an LDAP configuration entry.
+ */
+public class AmbariLdapConfigChangedEvent extends AmbariEvent {
+
+  private Long configurationId;
+
+  /**
+   * Constructor.
+   *
+   * @param eventType the type of event (not {@code null}).
+   */
+  public AmbariLdapConfigChangedEvent(AmbariEventType eventType, Long configurationId) {
+    super(eventType);
+    this.configurationId = configurationId;
+  }
+
+  public Long getConfigurationId() {
+    return configurationId;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java
index bcd6e39..57cdf6e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java
@@ -18,4 +18,4 @@ import java.util.Map;
 
 public interface LdapConfigurationFactory {
   AmbariLdapConfiguration createLdapConfiguration(Map<String, Object> configuration);
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
index 3ae4587..81f2a44 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
@@ -15,6 +15,7 @@
 
 package org.apache.ambari.server.ldap;
 
+import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider;
 import org.apache.ambari.server.ldap.service.AmbariLdapFacade;
 import org.apache.ambari.server.ldap.service.LdapConnectionService;
 import org.apache.ambari.server.ldap.service.LdapFacade;
@@ -35,6 +36,8 @@ public class LdapModule extends AbstractModule {
     bind(LdapConfigurationService.class).to(DefaultLdapConfigurationService.class);
     bind(LdapConnectionService.class).to(DefaultLdapConnectionService.class);
 
+    bind(AmbariLdapConfiguration.class).toProvider(AmbariLdapConfigurationProvider.class);
+
     install(new FactoryModuleBuilder().build(LdapConfigurationFactory.class));
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
new file mode 100644
index 0000000..7f3e8a9
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
@@ -0,0 +1,114 @@
+/*
+ * 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.ldap.service;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.events.AmbariLdapConfigChangedEvent;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
+import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
+import org.apache.ambari.server.security.authorization.AmbariLdapAuthenticationProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.eventbus.Subscribe;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * Provider implementation for LDAP configurations. It needs to be registered in the related GUICE module as a provider
+ * It's responsible for managing LDAP configurations in the application.
+ * Whenever requested, this provider returns an AmbariLdapConfiguration which is always in sync with the persisted LDAP
+ * configuration resource.
+ *
+ * The provider receives notifications on CRUD operations related to the persisted resource and reloads the cached
+ * configuration instance accordingly.
+ */
+@Singleton
+public class AmbariLdapConfigurationProvider implements Provider<AmbariLdapConfiguration> {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariLdapAuthenticationProvider.class);
+  private AmbariLdapConfiguration instance;
+
+  @Inject
+  private AmbariEventPublisher publisher;
+
+  @Inject
+  private Provider<AmbariConfigurationDAO> ambariConfigurationDAOProvider;
+
+  private Gson gson = new GsonBuilder().create();
+
+  @Inject
+  public AmbariLdapConfigurationProvider() {
+  }
+
+  @Inject
+  void register() {
+    publisher.register(this);
+  }
+
+  @Override
+  public AmbariLdapConfiguration get() {
+    return instance != null ? instance : loadInstance(null);
+  }
+
+  /**
+   * Loads the AmbariLdapConfiguration from the database.
+   *
+   * @param configurationId the configuration id
+   * @return the AmbariLdapConfiguration instance
+   */
+  private AmbariLdapConfiguration loadInstance(Long configurationId) {
+    AmbariConfigurationEntity configEntity = null;
+
+    LOGGER.info("Loading LDAP configuration ...");
+    if (null != configurationId) {
+
+      LOGGER.debug("Reloading configuration based on the provied id: {}", configurationId);
+      configEntity = ambariConfigurationDAOProvider.get().findByPK(configurationId);
+
+    } else {
+
+      LOGGER.debug("Initial loading of the ldap configuration ...");
+      configEntity = ambariConfigurationDAOProvider.get().getLdapConfiguration();
+
+    }
+
+    if (configEntity != null) {
+      Set propertyMaps = gson.fromJson(configEntity.getConfigurationBaseEntity().getConfigurationData(), Set.class);
+      instance = new AmbariLdapConfiguration((Map<String, Object>) propertyMaps.iterator().next());
+    }
+
+    LOGGER.info("Loaded LDAP configuration instance: [ {} ]", instance);
+
+    return instance;
+  }
+
+  @Subscribe
+  public void ambariLdapConfigChanged(AmbariLdapConfigChangedEvent event) {
+    LOGGER.info("LDAP config changed event received: {}", event);
+    loadInstance(event.getConfigurationId());
+    LOGGER.info("Refreshed LDAP config instance.");
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
index 683ed43..90a5ba7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
@@ -19,6 +19,7 @@ import java.util.Map;
 import java.util.Set;
 
 import javax.inject.Inject;
+import javax.inject.Provider;
 import javax.inject.Singleton;
 
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
@@ -54,6 +55,10 @@ public class AmbariLdapFacade implements LdapFacade {
   @Inject
   private LdapConnectionService ldapConnectionService;
 
+  //todo remove this, added for testing purposes only
+  @Inject
+  private Provider<AmbariLdapConfiguration> ambariLdapConfigurationProvider;
+
   @Inject
   public AmbariLdapFacade() {
   }
@@ -75,7 +80,7 @@ public class AmbariLdapFacade implements LdapFacade {
   @Override
   public void detectAttributes(AmbariLdapConfiguration ambariLdapConfiguration) {
     LOGGER.info("Detecting LDAP configuration attributes ...");
-    throw new UnsupportedOperationException("Not yet implemented");
+    LOGGER.info("LDAP config: {}", ambariLdapConfigurationProvider.get());
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/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
index 5710a7f..83293ef 100644
--- 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
@@ -16,8 +16,13 @@ package org.apache.ambari.server.orm.dao;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
+import javax.persistence.EntityExistsException;
+import javax.persistence.EntityNotFoundException;
+import javax.persistence.TypedQuery;
 
 import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.inject.persist.Transactional;
 
@@ -29,6 +34,8 @@ import com.google.inject.persist.Transactional;
 @Singleton
 public class AmbariConfigurationDAO extends CrudDAO<AmbariConfigurationEntity, Long> {
 
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariConfigurationDAO.class);
+
   @Inject
   public AmbariConfigurationDAO() {
     super(AmbariConfigurationEntity.class);
@@ -36,6 +43,47 @@ public class AmbariConfigurationDAO extends CrudDAO<AmbariConfigurationEntity, L
 
   @Transactional
   public void create(AmbariConfigurationEntity entity) {
+    // make  sure only one LDAP config entry exists
+    if ("ldap-configuration".equals(entity.getConfigurationBaseEntity().getType())) {
+      AmbariConfigurationEntity ldapConfigEntity = getLdapConfiguration();
+      if (ldapConfigEntity != null) {
+        LOGGER.error("Only one LDAP configuration entry can exist!");
+        throw new EntityExistsException("LDAP configuration entity already exists!");
+      }
+    }
     super.create(entity);
   }
+
+
+  @Transactional
+  public void update(AmbariConfigurationEntity entity) {
+    if (entity.getId() == null || findByPK(entity.getId()) == null) {
+      String msg = String.format("The entity with id [ %s ] is not found", entity.getId());
+      LOGGER.debug(msg);
+      throw new EntityNotFoundException(msg);
+    }
+
+    // updating the existing entity
+    super.merge(entity);
+    entityManagerProvider.get().flush();
+  }
+
+  /**
+   * Returns the LDAP configuration from the database.
+   *
+   * @return the configuration entity
+   */
+  @Transactional
+  public AmbariConfigurationEntity getLdapConfiguration() {
+    LOGGER.info("Looking up the LDAP configuration ....");
+    AmbariConfigurationEntity ldapConfigEntity = null;
+
+    TypedQuery<AmbariConfigurationEntity> query = entityManagerProvider.get().createNamedQuery(
+      "AmbariConfigurationEntity.findByType", AmbariConfigurationEntity.class);
+    query.setParameter("typeName", "ldap-configuration");
+
+    ldapConfigEntity = daoUtils.selectSingle(query);
+    LOGGER.info("Returned entity: {} ", ldapConfigEntity);
+    return ldapConfigEntity;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/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
index 34fa221..c9f4695 100644
--- 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
@@ -29,8 +29,8 @@ import javax.persistence.Table;
 @Table(name = "ambari_configuration")
 @NamedQueries({
   @NamedQuery(
-    name = "AmbariConfigurationEntity.findAll",
-    query = "select ace from AmbariConfigurationEntity ace")
+    name = "AmbariConfigurationEntity.findByType",
+    query = "select ace from AmbariConfigurationEntity ace where ace.configurationBaseEntity.type = :typeName")
 })
 
 public class AmbariConfigurationEntity {

http://git-wip-us.apache.org/repos/asf/ambari/blob/37f90058/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
index 2b7448e..b5978a5 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
@@ -28,6 +28,7 @@ import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.ldap.client.api.LdapConnection;
 import org.apache.directory.ldap.client.api.LdapConnectionConfig;
 import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,15 +47,18 @@ public class DefaultLdapConfigurationServiceTest {
 
     // WHEN
     LdapConnectionConfig config = new LdapConnectionConfig();
-    config.setLdapHost("localhost");
+    config.setLdapHost("172.22.112.167");
     config.setLdapPort(389);
     LdapConnection connection = new LdapNetworkConnection(config);
 
     // THEN
-    connection.anonymousBind();
+    connection.bind("CN=Robert Levas,CN=Users,DC=HWQE,DC=HORTONWORKS,DC=COM", "Hadoop1234");
 
+    String filter = FilterBuilder.and(
+      FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, "person"),
+      FilterBuilder.equal("name", "User1 Levas")).toString();
 
-    EntryCursor cursor = connection.search("dc=dev,dc=local", "(objectclass=*)", SearchScope.ONELEVEL);
+    EntryCursor cursor = connection.search("OU=levas,DC=hwqe,DC=hortonworks,DC=com", filter, SearchScope.SUBTREE);
 
     for (Entry entry : cursor) {
       assertNotNull(entry);


[10/38] ambari git commit: AMBARI-21893 : NameNode Heap Usage (Daily) metric alert status flips to UNKNOWN intermittently when AMS HTTPS is enabled. (avijayan)

Posted by lp...@apache.org.
AMBARI-21893 : NameNode Heap Usage (Daily) metric alert status flips to UNKNOWN intermittently when AMS HTTPS is enabled. (avijayan)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7fa7a6c1
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7fa7a6c1
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7fa7a6c1

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 7fa7a6c17607341e8a6888f3dd8b938dce7425ff
Parents: bb4645f
Author: Aravindan Vijayan <av...@hortonworks.com>
Authored: Tue Sep 12 17:01:51 2017 -0700
Committer: Aravindan Vijayan <av...@hortonworks.com>
Committed: Tue Sep 12 17:01:51 2017 -0700

----------------------------------------------------------------------
 .../server/upgrade/UpgradeCatalog260.java       | 30 +++++++++
 .../0.1.0/configuration/ams-ssl-client.xml      |  9 ---
 .../AMBARI_METRICS/0.1.0/package/scripts/ams.py | 10 +--
 .../0.1.0/package/scripts/params.py             | 10 ++-
 .../server/upgrade/UpgradeCatalog260Test.java   | 70 +++++++++++++++++++-
 5 files changed, 110 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7fa7a6c1/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
index d05f39a..2de85fc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
@@ -21,6 +21,7 @@ import static org.apache.ambari.server.view.ViewContextImpl.CORE_SITE;
 
 import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -29,6 +30,7 @@ import javax.persistence.EntityManager;
 import javax.persistence.Query;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.orm.dao.ArtifactDAO;
 import org.apache.ambari.server.orm.entities.ArtifactEntity;
@@ -122,6 +124,9 @@ public class UpgradeCatalog260 extends AbstractUpgradeCatalog {
   public static final String HOST_COMPONENT_DESIRED_STATE = "hostcomponentdesiredstate";
   public static final String HOST_COMPONENT_STATE = "hostcomponentstate";
 
+  public static final String AMS_SSL_CLIENT = "ams-ssl-client";
+  public static final String METRIC_TRUSTSTORE_ALIAS = "ssl.client.truststore.alias";
+
   /**
    * Logger.
    */
@@ -395,6 +400,7 @@ public class UpgradeCatalog260 extends AbstractUpgradeCatalog {
     removeSupersetFromDruid();
     ensureZeppelinProxyUserConfigs();
     updateKerberosDescriptorArtifacts();
+    updateAmsConfigs();
   }
 
   public int getCurrentVersionID() throws AmbariException, SQLException {
@@ -535,4 +541,28 @@ public class UpgradeCatalog260 extends AbstractUpgradeCatalog {
       }
     }
   }
+
+  protected void updateAmsConfigs() throws AmbariException {
+    AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
+    Clusters clusters = ambariManagementController.getClusters();
+    if (clusters != null) {
+      Map<String, Cluster> clusterMap = getCheckedClusterMap(clusters);
+      if (clusterMap != null && !clusterMap.isEmpty()) {
+        for (final Cluster cluster : clusterMap.values()) {
+
+
+          Config amsSslClient = cluster.getDesiredConfigByType(AMS_SSL_CLIENT);
+          if (amsSslClient != null) {
+            Map<String, String> amsSslClientProperties = amsSslClient.getProperties();
+
+            if (amsSslClientProperties.containsKey(METRIC_TRUSTSTORE_ALIAS)) {
+              LOG.info("Removing " + METRIC_TRUSTSTORE_ALIAS + " from " + AMS_SSL_CLIENT);
+              removeConfigurationPropertiesFromCluster(cluster, AMS_SSL_CLIENT, Collections.singleton(METRIC_TRUSTSTORE_ALIAS));
+            }
+
+          }
+        }
+      }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7fa7a6c1/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/configuration/ams-ssl-client.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/configuration/ams-ssl-client.xml b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/configuration/ams-ssl-client.xml
index cac39de..d75bba2 100644
--- a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/configuration/ams-ssl-client.xml
+++ b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/configuration/ams-ssl-client.xml
@@ -39,13 +39,4 @@
     </value-attributes>
     <on-ambari-upgrade add="true"/>
   </property>
-  <property>
-    <name>ssl.client.truststore.alias</name>
-    <value></value>
-    <description>Alias used to create certificate for AMS. (Default is hostname)</description>
-    <value-attributes>
-      <empty-value-valid>true</empty-value-valid>
-    </value-attributes>
-    <on-ambari-upgrade add="true"/>
-  </property>
 </configuration>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7fa7a6c1/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/ams.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/ams.py b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/ams.py
index 9a31ade..51e0756 100644
--- a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/ams.py
+++ b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/ams.py
@@ -515,10 +515,12 @@ def export_ca_certs(dir_path):
   truststore_p12 = os.path.join(tmpdir,'truststore.p12')
 
   if (params.metric_truststore_type.lower() == 'jks'):
-    # Convert truststore from JKS to PKCS12
-    cmd = format("{sudo} {java64_home}/bin/keytool -importkeystore -srckeystore {metric_truststore_path} -destkeystore {truststore_p12} -srcalias {metric_truststore_alias} -deststoretype PKCS12 -srcstorepass {metric_truststore_password} -deststorepass {metric_truststore_password}")
-    Execute(cmd,
-    )
+    if not params.metric_truststore_alias:
+      for alias in params.metric_truststore_alias_list:
+        # Convert truststore from JKS to PKCS12
+        cmd = format("{sudo} {java64_home}/bin/keytool -importkeystore -srckeystore {metric_truststore_path} -destkeystore {truststore_p12} -srcalias " + alias + " -deststoretype PKCS12 -srcstorepass {metric_truststore_password} -deststorepass {metric_truststore_password}")
+        Execute(cmd,
+        )
     truststore = truststore_p12
 
   # Export all CA certificates from the truststore to the conf directory

http://git-wip-us.apache.org/repos/asf/ambari/blob/7fa7a6c1/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/params.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/params.py b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/params.py
index 756da26..0242b73 100644
--- a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/params.py
+++ b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/package/scripts/params.py
@@ -100,11 +100,15 @@ else:
 metric_truststore_path= default("/configurations/ams-ssl-client/ssl.client.truststore.location", "")
 metric_truststore_type= default("/configurations/ams-ssl-client/ssl.client.truststore.type", "")
 metric_truststore_password= default("/configurations/ams-ssl-client/ssl.client.truststore.password", "")
-metric_truststore_alias = default("/configurations/ams-ssl-client/ssl.client.truststore.alias", None)
-if not metric_truststore_alias:
-  metric_truststore_alias = metric_collector_host
 metric_truststore_ca_certs='ca.pem'
 
+metric_truststore_alias_list = []
+for host in ams_collector_hosts.split(","):
+  metric_truststore_alias = default("/configurations/ams-ssl-client/{host}.ssl.client.truststore.alias", None)
+  if not metric_truststore_alias:
+    metric_truststore_alias = host
+  metric_truststore_alias_list.append(metric_truststore_alias)
+
 agent_cache_dir = config['hostLevelParams']['agentCacheDir']
 service_package_folder = config['commandParams']['service_package_folder']
 stack_name = default("/hostLevelParams/stack_name", None)

http://git-wip-us.apache.org/repos/asf/ambari/blob/7fa7a6c1/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
index 33c29bc..b70f37b 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
@@ -23,6 +23,7 @@ import static org.easymock.EasyMock.anyString;
 import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.createNiceMock;
 import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
@@ -30,6 +31,7 @@ import static org.easymock.EasyMock.newCapture;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.reset;
 import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertTrue;
 
 import java.io.File;
 import java.net.URL;
@@ -40,16 +42,19 @@ import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import javax.persistence.EntityManager;
 
+import com.google.common.collect.Maps;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.AmbariManagementControllerImpl;
 import org.apache.ambari.server.controller.KerberosHelper;
 import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.orm.DBAccessor;
@@ -67,7 +72,9 @@ import org.apache.ambari.server.state.kerberos.KerberosDescriptorFactory;
 import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
 import org.apache.ambari.server.state.stack.OsFamily;
 import org.easymock.Capture;
+import org.easymock.EasyMock;
 import org.easymock.EasyMockRunner;
+import org.easymock.EasyMockSupport;
 import org.easymock.Mock;
 import org.easymock.MockType;
 import org.junit.After;
@@ -480,8 +487,8 @@ public class UpgradeCatalog260Test {
   }
 
   public void verifyGetCurrentVersionID(Capture<String[]> scdcaptureKey, Capture<String[]> scdcaptureValue) {
-    Assert.assertTrue(Arrays.equals(scdcaptureKey.getValue(), new String[]{UpgradeCatalog260.STATE_COLUMN}));
-    Assert.assertTrue(Arrays.equals(scdcaptureValue.getValue(), new String[]{UpgradeCatalog260.CURRENT}));
+    assertTrue(Arrays.equals(scdcaptureKey.getValue(), new String[]{UpgradeCatalog260.STATE_COLUMN}));
+    assertTrue(Arrays.equals(scdcaptureValue.getValue(), new String[]{UpgradeCatalog260.CURRENT}));
   }
 
   public void expectUpdateServiceComponentDesiredStateTable(Capture<DBColumnInfo> scdstadd1, Capture<DBColumnInfo> scdstalter1, Capture<DBColumnInfo> scdstadd2, Capture<DBColumnInfo> scdstalter2) throws SQLException {
@@ -625,7 +632,7 @@ public class UpgradeCatalog260Test {
 
     verify(clusters, cluster, zeppelinEnvConf, coreSiteConf, coreSiteConfNew, controller);
 
-    Assert.assertTrue(captureCoreSiteConfProperties.hasCaptured());
+    assertTrue(captureCoreSiteConfProperties.hasCaptured());
     Assert.assertEquals("existing_value", captureCoreSiteConfProperties.getValue().get("hadoop.proxyuser.zeppelin_user.hosts"));
     Assert.assertEquals("*", captureCoreSiteConfProperties.getValue().get("hadoop.proxyuser.zeppelin_user.groups"));
   }
@@ -673,4 +680,61 @@ public class UpgradeCatalog260Test {
     Assert.assertNull(kerberosDescriptorUpdated.getService("RANGER_KMS").getComponent("RANGER_KMS_SERVER").getIdentity("/smokeuser"));
 
   }
+
+  @Test
+  public void testUpdateAmsConfigs() throws Exception{
+
+    Map<String, String> oldProperties = new HashMap<String, String>() {
+      {
+        put("ssl.client.truststore.location", "/some/location");
+        put("ssl.client.truststore.alias", "test_alias");
+      }
+    };
+    Map<String, String> newProperties = new HashMap<String, String>() {
+      {
+        put("ssl.client.truststore.location", "/some/location");
+      }
+    };
+
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+    Clusters clusters = easyMockSupport.createNiceMock(Clusters.class);
+    final Cluster cluster = easyMockSupport.createNiceMock(Cluster.class);
+    Config mockAmsSslClient = easyMockSupport.createNiceMock(Config.class);
+
+    expect(clusters.getClusters()).andReturn(new HashMap<String, Cluster>() {{
+      put("normal", cluster);
+    }}).once();
+    expect(cluster.getDesiredConfigByType("ams-ssl-client")).andReturn(mockAmsSslClient).atLeastOnce();
+    expect(mockAmsSslClient.getProperties()).andReturn(oldProperties).anyTimes();
+
+    Injector injector = easyMockSupport.createNiceMock(Injector.class);
+    expect(injector.getInstance(Gson.class)).andReturn(null).anyTimes();
+    expect(injector.getInstance(MaintenanceStateHelper.class)).andReturn(null).anyTimes();
+
+    replay(injector, clusters, mockAmsSslClient, cluster);
+
+    AmbariManagementControllerImpl controller = createMockBuilder(AmbariManagementControllerImpl.class)
+      .addMockedMethod("createConfiguration")
+      .addMockedMethod("getClusters", new Class[] { })
+      .addMockedMethod("createConfig")
+      .withConstructor(createNiceMock(ActionManager.class), clusters, injector)
+      .createNiceMock();
+
+    Injector injector2 = easyMockSupport.createNiceMock(Injector.class);
+    Capture<Map> propertiesCapture = EasyMock.newCapture();
+
+    expect(injector2.getInstance(AmbariManagementController.class)).andReturn(controller).anyTimes();
+    expect(controller.getClusters()).andReturn(clusters).anyTimes();
+    expect(controller.createConfig(anyObject(Cluster.class), anyObject(StackId.class), anyString(), capture(propertiesCapture), anyString(),
+      anyObject(Map.class))).andReturn(createNiceMock(Config.class)).once();
+
+    replay(controller, injector2);
+    new UpgradeCatalog260(injector2).updateAmsConfigs();
+    easyMockSupport.verifyAll();
+
+    Map<String, String> updatedProperties = propertiesCapture.getValue();
+    assertTrue(Maps.difference(newProperties, updatedProperties).areEqual());
+  }
+
 }


[05/38] ambari git commit: AMBARI-21902. Ambari is setting "atlas.graph.storage.hostname" to hbase hostname, instead it should set the zookeeper quorum. (Ayub Pathan via stoader)

Posted by lp...@apache.org.
AMBARI-21902. Ambari is setting "atlas.graph.storage.hostname" to hbase hostname, instead it should set the zookeeper quorum. (Ayub Pathan via stoader)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/5113e995
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/5113e995
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/5113e995

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 5113e995f27b4b357ca99650cee5c95a7881c619
Parents: f89dcd7
Author: Toader, Sebastian <st...@hortonworks.com>
Authored: Tue Sep 12 15:29:53 2017 +0200
Committer: Toader, Sebastian <st...@hortonworks.com>
Committed: Tue Sep 12 18:04:40 2017 +0200

----------------------------------------------------------------------
 .../BlueprintConfigurationProcessor.java        |  2 +-
 .../BlueprintConfigurationProcessorTest.java    | 29 ++++++++++++--------
 2 files changed, 19 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/5113e995/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
index 3538945..5a6e2cc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
@@ -2730,7 +2730,7 @@ public class BlueprintConfigurationProcessor {
     atlasPropsMap.put("atlas.kafka.bootstrap.servers", new MultipleHostTopologyUpdater("KAFKA_BROKER"));
     atlasPropsMap.put("atlas.kafka.zookeeper.connect", new MultipleHostTopologyUpdater("ZOOKEEPER_SERVER"));
     atlasPropsMap.put("atlas.graph.index.search.solr.zookeeper-url", new MultipleHostTopologyUpdater("ZOOKEEPER_SERVER", ',', false, true, true));
-    atlasPropsMap.put("atlas.graph.storage.hostname", new MultipleHostTopologyUpdater("HBASE_MASTER"));
+    atlasPropsMap.put("atlas.graph.storage.hostname", new MultipleHostTopologyUpdater("ZOOKEEPER_SERVER"));
     atlasPropsMap.put("atlas.audit.hbase.zookeeper.quorum", new MultipleHostTopologyUpdater("ZOOKEEPER_SERVER"));
 
     // RANGER_ADMIN

http://git-wip-us.apache.org/repos/asf/ambari/blob/5113e995/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java
index 734dd7e..68d6349 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java
@@ -4997,6 +4997,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
   @Test
   public void testAtlas() throws Exception {
     final String expectedHostGroupName = "host_group_1";
+    final String zkHostGroupName = "zk_host_group";
     final String host1 = "c6401.ambari.apache.org";
     final String host2 = "c6402.ambari.apache.org";
     final String host3 = "c6403.ambari.apache.org";
@@ -5015,18 +5016,24 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
 
-    Collection<String> hgComponents = new HashSet<>();
-    hgComponents.add("KAFKA_BROKER");
-    hgComponents.add("ZOOKEEPER_SERVER");
-    hgComponents.add("HBASE_MASTER");
+    Collection<String> hg1Components = new HashSet<>();
+    hg1Components.add("KAFKA_BROKER");
+    hg1Components.add("HBASE_MASTER");
     List<String> hosts = new ArrayList<>();
     hosts.add(host1);
     hosts.add(host2);
-    hosts.add(host3);
-    TestHostGroup group1 = new TestHostGroup(expectedHostGroupName, hgComponents, hosts);
+    TestHostGroup group1 = new TestHostGroup(expectedHostGroupName, hg1Components, hosts);
+
+    // Place ZOOKEEPER_SERVER in separate host group/host other
+    // than ATLAS
+    Collection<String> zkHostGroupComponents = new HashSet<>();
+    zkHostGroupComponents.add("ZOOKEEPER_SERVER");
+
+    TestHostGroup group2 = new TestHostGroup(zkHostGroupName, zkHostGroupComponents, Collections.singletonList(host3));
 
     Collection<TestHostGroup> hostGroups = new HashSet<>();
     hostGroups.add(group1);
+    hostGroups.add(group2);
 
     ClusterTopology topology = createClusterTopology(bp, clusterConfig, hostGroups);
     BlueprintConfigurationProcessor updater = new BlueprintConfigurationProcessor(topology);
@@ -5037,29 +5044,29 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     List<String> hostArray =
       Arrays.asList(atlasProperties.get("atlas.kafka.bootstrap.servers").split(","));
     List<String> expected =
-      Arrays.asList("c6401.ambari.apache.org:6667", "c6402.ambari.apache.org:6667", "c6403.ambari.apache.org:6667");
+      Arrays.asList("c6401.ambari.apache.org:6667", "c6402.ambari.apache.org:6667");
 
     Assert.assertTrue(hostArray.containsAll(expected) && expected.containsAll(hostArray));
 
     hostArray = Arrays.asList(atlasProperties.get("atlas.kafka.zookeeper.connect").split(","));
     expected =
-      Arrays.asList("c6401.ambari.apache.org:2181", "c6402.ambari.apache.org:2181", "c6403.ambari.apache.org:2181");
+      Arrays.asList("c6403.ambari.apache.org:2181");
     Assert.assertTrue(hostArray.containsAll(expected) && expected.containsAll(hostArray));
 
 
     hostArray = Arrays.asList(atlasProperties.get("atlas.graph.index.search.solr.zookeeper-url").split(","));
     expected =
-      Arrays.asList("c6401.ambari.apache.org:2181/ambari-solr", "c6402.ambari.apache.org:2181/ambari-solr", "c6403.ambari.apache.org:2181/ambari-solr");
+      Arrays.asList("c6403.ambari.apache.org:2181/ambari-solr");
     Assert.assertTrue(hostArray.containsAll(expected) && expected.containsAll(hostArray));
 
     hostArray = Arrays.asList(atlasProperties.get("atlas.graph.storage.hostname").split(","));
     expected =
-      Arrays.asList("c6401.ambari.apache.org", "c6402.ambari.apache.org", "c6403.ambari.apache.org");
+      Arrays.asList("c6403.ambari.apache.org");
     Assert.assertTrue(hostArray.containsAll(expected) && expected.containsAll(hostArray));
 
     hostArray = Arrays.asList(atlasProperties.get("atlas.audit.hbase.zookeeper.quorum").split(","));
     expected =
-      Arrays.asList("c6401.ambari.apache.org", "c6402.ambari.apache.org", "c6403.ambari.apache.org");
+      Arrays.asList("c6403.ambari.apache.org");
     Assert.assertTrue(hostArray.containsAll(expected) && expected.containsAll(hostArray));
   }
 


[30/38] ambari git commit: AMBARI-21307 Groups for the test user returned to the caller

Posted by lp...@apache.org.
AMBARI-21307 Groups for the test user returned to the caller


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/faf95340
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/faf95340
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/faf95340

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: faf953409e8b0796569050550c0056df69e1fdc6
Parents: 3ad545a
Author: lpuskas <lp...@apache.org>
Authored: Tue Aug 8 15:50:29 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:30 2017 +0200

----------------------------------------------------------------------
 .../api/services/ldap/LdapRestService.java      | 16 +++++-
 .../server/ldap/AmbariLdapConfiguration.java    |  2 +-
 .../apache/ambari/server/ldap/LdapModule.java   |  3 +
 .../server/ldap/service/AmbariLdapFacade.java   |  3 +-
 .../ambari/server/ldap/service/LdapFacade.java  |  3 +-
 ...efaultLdapConfigurationValidatorService.java | 25 ++++++---
 .../ad/DefaultLdapConnectionService.java        |  2 +-
 ...ltLdapConfigurationValidatorServiceTest.java | 59 +++-----------------
 8 files changed, 49 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/faf95340/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
index 33b10fa..8578204 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
@@ -28,6 +28,8 @@
 
 package org.apache.ambari.server.api.services.ldap;
 
+import java.util.Set;
+
 import javax.inject.Inject;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.POST;
@@ -41,12 +43,16 @@ import org.apache.ambari.server.api.services.BaseService;
 import org.apache.ambari.server.api.services.Result;
 import org.apache.ambari.server.api.services.ResultImpl;
 import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.controller.internal.ResourceImpl;
+import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
 import org.apache.ambari.server.ldap.LdapConfigurationFactory;
 import org.apache.ambari.server.ldap.service.LdapFacade;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Sets;
+
 /**
  * Endpoint designated to LDAP specific operations.
  */
@@ -68,6 +74,8 @@ public class LdapRestService extends BaseService {
   @Consumes(MediaType.APPLICATION_JSON)
   public Response validateConfiguration(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
 
+    Set<String> groups = Sets.newHashSet();
+
     Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
     try {
 
@@ -86,7 +94,11 @@ public class LdapRestService extends BaseService {
         case "test-attributes":
 
           LOGGER.info("Testing LDAP attributes ....");
-          ldapFacade.checkLdapAttibutes(ldapCheckConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
+          groups = ldapFacade.checkLdapAttibutes(ldapCheckConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
+          // todo factor out the resource creation, design better the structure in the response
+          Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
+          resource.setProperty("groups", groups);
+          result.getResultTree().addChild(resource, "payload");
 
           break;
         case "detect-attributes":
@@ -101,7 +113,7 @@ public class LdapRestService extends BaseService {
       }
 
     } catch (Exception e) {
-      result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e));
+      result.setResultStatus(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e));
     }
 
     return Response.status(result.getStatus().getStatusCode()).entity(getResultSerializer().serialize(result)).build();

http://git-wip-us.apache.org/repos/asf/ambari/blob/faf95340/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
index a6ff80b..8ab587b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
@@ -48,7 +48,7 @@ public class AmbariLdapConfiguration {
     MANAGER_PASSWORD("ambari.ldap.managerpassword"),
     USER_OBJECT_CLASS("ambari.ldap.user.object.class"),
     USER_NAME_ATTRIBUTE("ambari.ldap.user.name.attribute"),
-    USER_SEARCH_BASE("ambari.ldap.user.search.Base"),
+    USER_SEARCH_BASE("ambari.ldap.user.search.base"),
 
     GROUP_OBJECT_CLASS("ambari.ldap.group.object.class"),
     GROUP_NAME_ATTRIBUTE("ambari.ldap.group.name.attribute"),

http://git-wip-us.apache.org/repos/asf/ambari/blob/faf95340/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
index 545f220..1b49159 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
@@ -16,8 +16,10 @@
 package org.apache.ambari.server.ldap;
 
 import org.apache.ambari.server.ldap.service.AmbariLdapFacade;
+import org.apache.ambari.server.ldap.service.LdapConnectionService;
 import org.apache.ambari.server.ldap.service.LdapFacade;
 import org.apache.ambari.server.ldap.service.ad.DefaultLdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.service.ad.DefaultLdapConnectionService;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
@@ -31,6 +33,7 @@ public class LdapModule extends AbstractModule {
   protected void configure() {
     bind(LdapFacade.class).to(AmbariLdapFacade.class);
     bind(LdapConfigurationValidatorService.class).to(DefaultLdapConfigurationValidatorService.class);
+    bind(LdapConnectionService.class).to(DefaultLdapConnectionService.class);
 
     install(new FactoryModuleBuilder().build(LdapConfigurationFactory.class));
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/faf95340/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
index abb464b..eec47ce 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
@@ -79,7 +79,7 @@ public class AmbariLdapFacade implements LdapFacade {
   }
 
   @Override
-  public void checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ldapConfiguration) throws AmbariLdapException {
+  public Set<String> checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ldapConfiguration) throws AmbariLdapException {
     String userName = getTestUserNameFromParameters(parameters);
     String testUserPass = getTestUserPasswordFromParameters(parameters);
 
@@ -95,6 +95,7 @@ public class AmbariLdapFacade implements LdapFacade {
     LOGGER.info("Testing LDAP group attributes with test user dn: {}", userDn);
     Set<String> groups = ldapConfigurationValidatorService.checkGroupAttributes(ldapConnection, userDn, ldapConfiguration);
 
+    return groups;
   }
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/faf95340/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
index 7bb1198..eadff7d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
@@ -15,6 +15,7 @@
 package org.apache.ambari.server.ldap.service;
 
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
 
@@ -47,5 +48,5 @@ public interface LdapFacade {
    * @param ambariLdapConfiguration configutration instance with available attributes
    * @throws AmbariLdapException if the attribute checking fails
    */
-  void checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;
+  Set<String> checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/faf95340/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java
index 838ef4c..a8503ca 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java
@@ -37,7 +37,6 @@ import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.ldap.client.api.LdapConnection;
-import org.apache.directory.ldap.client.api.LdapNetworkConnection;
 import org.apache.directory.ldap.client.api.search.FilterBuilder;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
 import org.slf4j.Logger;
@@ -84,18 +83,18 @@ public class DefaultLdapConfigurationValidatorService implements LdapConfigurati
    * @param testUserName            the test username
    * @param testPassword            the test password
    * @param ambariLdapConfiguration configuration instance holding ldap configuration details
+   * @return the DN of the test user
    * @throws AmbariException if the attributes are not valid or any errors occurs
    */
   @Override
   public String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
-    LdapNetworkConnection connection = null;
     SearchCursor searchCursor = null;
     String userDn = null;
     try {
       LOGGER.info("Checking user attributes for user {} r ...", testUserName);
 
       // bind anonimously or with manager data
-      bind(ambariLdapConfiguration, connection);
+      bind(ambariLdapConfiguration, ldapConnection);
 
       // set up a filter based on the provided attributes
       String filter = FilterBuilder.and(
@@ -104,7 +103,7 @@ public class DefaultLdapConfigurationValidatorService implements LdapConfigurati
         .toString();
 
       LOGGER.info("Searching for the user: {} using the search filter: {}", testUserName, filter);
-      EntryCursor entryCursor = connection.search(new Dn(ambariLdapConfiguration.userSearchBase()), filter, SearchScope.SUBTREE);
+      EntryCursor entryCursor = ldapConnection.search(new Dn(ambariLdapConfiguration.userSearchBase()), filter, SearchScope.SUBTREE);
 
       // collecting search result entries
       List<Entry> users = Lists.newArrayList();
@@ -128,7 +127,7 @@ public class DefaultLdapConfigurationValidatorService implements LdapConfigurati
       throw new AmbariLdapException(e.getMessage(), e);
 
     } finally {
-      closeResources(connection, searchCursor);
+      closeResources(ldapConnection, searchCursor);
     }
     return userDn;
   }
@@ -172,14 +171,19 @@ public class DefaultLdapConfigurationValidatorService implements LdapConfigurati
       throw new AmbariLdapException(e.getMessage(), e);
 
     } finally {
-
       closeResources(ldapConnection, searchCursor);
-
     }
 
     return processGroupResults(groupResponses, ambariLdapConfiguration);
   }
 
+  /**
+   * Binds to the LDAP server (anonimously or wit manager credentials)
+   *
+   * @param ambariLdapConfiguration configuration instance
+   * @param connection              connection instance
+   * @throws LdapException if the bind operation fails
+   */
   private void bind(AmbariLdapConfiguration ambariLdapConfiguration, LdapConnection connection) throws LdapException {
     LOGGER.info("Connecting to LDAP ....");
     if (!ambariLdapConfiguration.bindAnonimously()) {
@@ -198,6 +202,13 @@ public class DefaultLdapConfigurationValidatorService implements LdapConfigurati
   }
 
 
+  /**
+   * Extracts meaningful values from the search result.
+   *
+   * @param groupResponses          the result entries returned by the search
+   * @param ambariLdapConfiguration holds the keys of the meaningful attributes
+   * @return a set with the group names the test user belongs to
+   */
   private Set<String> processGroupResults(Set<Response> groupResponses, AmbariLdapConfiguration ambariLdapConfiguration) {
     Set<String> groupStrSet = Sets.newHashSet();
     for (Response response : groupResponses) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/faf95340/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java
index b5559d9..25dc1f2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java
@@ -56,7 +56,7 @@ public class DefaultLdapConnectionService implements LdapConnectionService {
     ldapConnectionConfig.setLdapPort(ambariAmbariLdapConfiguration.ldapServerPort());
     ldapConnectionConfig.setUseSsl(ambariAmbariLdapConfiguration.useSSL());
 
-    //todo set the other values as required
+    // todo set the other values as required
     return ldapConnectionConfig;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/faf95340/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java
index 5c9d304..663ea12 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java
@@ -18,23 +18,15 @@ import static org.junit.Assert.assertNotNull;
 
 import java.util.Map;
 
-import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
 import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
 import org.apache.ambari.server.ldap.service.LdapConnectionService;
 import org.apache.directory.api.ldap.model.cursor.EntryCursor;
-import org.apache.directory.api.ldap.model.cursor.SearchCursor;
 import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.message.Response;
-import org.apache.directory.api.ldap.model.message.SearchRequest;
-import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
-import org.apache.directory.api.ldap.model.message.SearchResultEntry;
 import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.ldap.client.api.LdapConnection;
 import org.apache.directory.ldap.client.api.LdapConnectionConfig;
 import org.apache.directory.ldap.client.api.LdapNetworkConnection;
-import org.apache.directory.ldap.client.api.search.FilterBuilder;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
 import org.junit.Test;
 import org.slf4j.Logger;
@@ -75,57 +67,24 @@ public class DefaultLdapConfigurationValidatorServiceTest {
 
   @Test
   public void testCheckUserAttributes() throws Exception {
+    // GIVEN
     Map<String, Object> ldapPropsMap = Maps.newHashMap();
 
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), false);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
     ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
     ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
     ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
+
     ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE.propertyName(), SchemaConstants.UNIQUE_MEMBER_AT);
     ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_SEARCH_BASE.propertyName(), "dc=example,dc=com");
 
-    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
-
-
-    try {
-      LOGGER.info("Authenticating user {} against the LDAP server ...", TEST_USER);
-      LdapConnectionService connectionService = new DefaultLdapConnectionService();
-      LdapNetworkConnection connection = connectionService.createLdapConnection(ambariLdapConfiguration);
-
-      String filter = FilterBuilder.and(
-        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
-        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), TEST_USER))
-        .toString();
-
-      SearchRequest searchRequest = new SearchRequestImpl();
-      searchRequest.setBase(new Dn(ambariLdapConfiguration.baseDn()));
-      searchRequest.setFilter(filter);
-      searchRequest.setScope(SearchScope.SUBTREE);
 
-      LOGGER.info("loking up user: {} based on the filtr: {}", TEST_USER, filter);
-
-      connection.bind();
-      SearchCursor searchCursor = connection.search(searchRequest);
-
-      while (searchCursor.next()) {
-        Response response = searchCursor.get();
-
-        // process the SearchResultEntry
-        if (response instanceof SearchResultEntry) {
-          Entry resultEntry = ((SearchResultEntry) response).getEntry();
-          System.out.println(resultEntry);
-        }
-      }
-
-      searchCursor.close();
-
-    } catch (Exception e) {
-      throw new AmbariException("Error during user authentication check", e);
-    }
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
+    LdapConnectionService connectionService = new DefaultLdapConnectionService();
+    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
 
+    ldapConfigurationValidatorService.checkUserAttributes(ldapConnection, "einstein", "", ambariLdapConfiguration);
   }
 
   @Test
@@ -138,8 +97,6 @@ public class DefaultLdapConfigurationValidatorServiceTest {
     ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
     ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
 
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
 
     ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC);
     ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT);


[04/38] ambari git commit: AMBARI-21634. Make sure Ambari also considers NIS users (Aman Poonia via ncole)

Posted by lp...@apache.org.
AMBARI-21634. Make sure Ambari also considers NIS users (Aman Poonia via ncole)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f89dcd7d
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f89dcd7d
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f89dcd7d

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: f89dcd7d03d18a57543f2a86653345ad3ab00095
Parents: 02bea54
Author: Nate Cole <nc...@hortonworks.com>
Authored: Tue Sep 12 10:19:41 2017 -0400
Committer: Nate Cole <nc...@hortonworks.com>
Committed: Tue Sep 12 10:19:41 2017 -0400

----------------------------------------------------------------------
 .../src/main/python/ambari_agent/HostInfo.py    | 29 +++++++++++---------
 .../test/python/ambari_agent/TestHostInfo.py    | 21 ++++----------
 2 files changed, 21 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/f89dcd7d/ambari-agent/src/main/python/ambari_agent/HostInfo.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/HostInfo.py b/ambari-agent/src/main/python/ambari_agent/HostInfo.py
index 5f96df5..b8545cc 100644
--- a/ambari-agent/src/main/python/ambari_agent/HostInfo.py
+++ b/ambari-agent/src/main/python/ambari_agent/HostInfo.py
@@ -21,6 +21,7 @@ limitations under the License.
 import glob
 import logging
 import os
+import pwd
 import re
 import shlex
 import socket
@@ -170,13 +171,13 @@ class HostInfoLinux(HostInfo):
     "hue", "yarn", "tez", "storm", "falcon", "kafka", "knox", "ams",
     "hadoop", "spark", "accumulo", "atlas", "mahout", "ranger", "kms", "zeppelin"
   ]
-  
+
   # Default set of directories that are checked for existence of files and folders
   DEFAULT_BASEDIRS = [
     "/etc", "/var/run", "/var/log", "/usr/lib", "/var/lib", "/var/tmp", "/tmp", "/var",
     "/hadoop", "/usr/hdp"
   ]
-  
+
   # Exact directories names which are checked for existance
   EXACT_DIRECTORIES = [
     "/kafka-logs"
@@ -193,15 +194,17 @@ class HostInfoLinux(HostInfo):
     super(HostInfoLinux, self).__init__(config)
 
   def checkUsers(self, users, results):
-    f = open('/etc/passwd', 'r')
-    for userLine in f:
-      fields = userLine.split(":")
-      if fields[0] in users:
-        result = {}
-        result['name'] = fields[0]
-        result['homeDir'] = fields[5]
-        result['status'] = "Available"
-        results.append(result)
+    for user in users:
+      try:
+          pw = pwd.getpwnam(user)
+          result = {}
+          result['name'] = pw.pw_name
+          result['homeDir'] = pw.pw_dir
+          result['status'] = "Available"
+          results.append(result)
+      except Exception as e:
+          #User doesnot exist, so skip it
+          pass
 
   def checkFolders(self, basePaths, projectNames, exactDirectories, existingUsers, dirs):
     foldersToIgnore = []
@@ -216,13 +219,13 @@ class HostInfoLinux(HostInfo):
             obj['type'] = self.dirType(path)
             obj['name'] = path
             dirs.append(obj)
-            
+
       for path in exactDirectories:
         if os.path.exists(path):
           obj = {}
           obj['type'] = self.dirType(path)
           obj['name'] = path
-          dirs.append(obj)     
+          dirs.append(obj)
     except:
       logger.exception("Checking folders failed")
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f89dcd7d/ambari-agent/src/test/python/ambari_agent/TestHostInfo.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestHostInfo.py b/ambari-agent/src/test/python/ambari_agent/TestHostInfo.py
index cb20f4e..3c46268 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestHostInfo.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestHostInfo.py
@@ -59,26 +59,15 @@ class TestHostInfo(TestCase):
 
       self.assertTrue(item in names)
 
-  @patch('os.path.exists')
-  @patch('__builtin__.open')
-  def test_checkUsers(self, builtins_open_mock, path_mock):
-    builtins_open_mock.return_value = [
-      "hdfs:x:493:502:Hadoop HDFS:/usr/lib/hadoop:/bin/bash",
-      "zookeeper:x:492:502:ZooKeeper:/var/run/zookeeper:/bin/bash"]
-    path_mock.side_effect = [False, True, False]
-
+  def test_checkUsers(self):
     hostInfo = HostInfoLinux()
     results = []
-    hostInfo.checkUsers(["zookeeper", "hdfs"], results)
-    self.assertEqual(2, len(results))
+    hostInfo.checkUsers(["root", "zxlmnap12341234"], results)
+    self.assertEqual(1, len(results))
     newlist = sorted(results, key=lambda k: k['name'])
-    self.assertTrue(newlist[0]['name'], "hdfs")
-    self.assertTrue(newlist[1]['name'], "zookeeper")
-    self.assertTrue(newlist[0]['homeDir'], "/usr/lib/hadoop")
-    self.assertTrue(newlist[1]['homeDir'], "/var/run/zookeeper")
+    self.assertTrue(newlist[0]['name'], "root")
+    self.assertTrue(newlist[0]['homeDir'], "/root")
     self.assertTrue(newlist[0]['status'], "Available")
-    self.assertTrue(newlist[1]['status'], "Invalid home directory")
-    print(path_mock.mock_calls)
 
   @patch.object(OSCheck, "get_os_type")
   @patch('os.umask')


[34/38] ambari git commit: AMBARI-21307 Add all known LDAP properties to AmbariConfigurationEnum (benyoka)

Posted by lp...@apache.org.
AMBARI-21307 Add all known LDAP properties to AmbariConfigurationEnum (benyoka)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2750e627
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2750e627
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2750e627

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 2750e6270c16b9788ad64d72656e5c8320e2e5ba
Parents: 37f9005
Author: Balazs Bence Sari <be...@apache.org>
Authored: Mon Sep 4 12:45:07 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:31 2017 +0200

----------------------------------------------------------------------
 .../ambari/server/ldap/AmbariLdapConfiguration.java  | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/2750e627/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
index b1cbced..e913e77 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
@@ -40,22 +40,35 @@ public class AmbariLdapConfiguration {
     USE_SSL("ambari.ldap.usessl"),
     LDAP_SERVER_HOST("ambari.ldap.server.host"),
     LDAP_SERVER_PORT("ambari.ldap.server.port"),
+    LDAP_TRUSTSTORE("ambari.ldap.truststore"),
     LDAP_TRUSTSTORE_TYPE("ambari.ldap.truststore.type"),
     LDAP_TRUSTSTORE_PATH("ambari.ldap.truststore.path"),
+    LDAP_TRUSTSTORE_PASSWORD("ambari.ldap.truststore.password"),
     BASE_DN("ambari.ldap.bind.dn"),
+    REFERRAL("ambari.ldap.referral"),
+    PAGINATION_ENABLED("ambari.ldap.pagination.enabled"),
 
     BIND_ANONIMOUSLY("ambari.ldap.bindanonymously"),
     MANAGER_DN("ambari.ldap.managerdn"),
     MANAGER_PASSWORD("ambari.ldap.managerpassword"),
     USER_OBJECT_CLASS("ambari.ldap.user.object.class"),
     USER_NAME_ATTRIBUTE("ambari.ldap.user.name.attribute"),
+    USER_NAME_FORCE_LOWERCASE("ambari.ldap.username.force.lowercase"),
     USER_SEARCH_BASE("ambari.ldap.user.search.base"),
+    SYNC_USER_MEMBER_REPLACE_PATTERN("ambari.ldap.sync.user.member.replacepattern"),
+    SYNC_USER_MEMBER_FILTER("ambari.ldap.sync.user.member_filter"),
 
+    ADMIN_GROUP_MAPPING_RULES ("ambari.ldap.admin.group.mappingrules"),
     GROUP_OBJECT_CLASS("ambari.ldap.group.object.class"),
     GROUP_NAME_ATTRIBUTE("ambari.ldap.group.name.attribute"),
     GROUP_MEMBER_ATTRIBUTE("ambari.ldap.group.member.attribute"),
     GROUP_SEARCH_BASE("ambari.ldap.group.search.base"),
-    DN_ATTRIBUTE("authentication.ldap.dnAttribute");
+    SYNC_GROUP_MEMBER_REPLACE_PATTERN("ambari.ldap.sync.group.member.replacepattern"),
+    SYNC_GROUP_MEMBER_FILTER("ambari.ldap.sync.group.member_filter"),
+    DN_ATTRIBUTE("authentication.ldap.dnAttribute"),
+
+    TEST_USER_NAME("ambari.ldap.test.user.name"),
+    TEST_USER_PASSWORD("ambari.ldap.test.user.password");
 
     private String propertyName;
 


[03/38] ambari git commit: AMBARI-21785. Component restart instructions in case of OUT_OF_SYNC (alexantonenko)

Posted by lp...@apache.org.
AMBARI-21785. Component restart instructions in case of OUT_OF_SYNC (alexantonenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/02bea547
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/02bea547
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/02bea547

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 02bea547cd71e6aff173f04d0154b25ebe85432a
Parents: 001f290
Author: Alex Antonenko <aa...@hortonworks.com>
Authored: Tue Sep 12 16:26:12 2017 +0300
Committer: Alex Antonenko <aa...@hortonworks.com>
Committed: Tue Sep 12 16:26:12 2017 +0300

----------------------------------------------------------------------
 ambari-web/app/messages.js                          |  2 ++
 .../admin/stack_upgrade/stack_upgrade_wizard.hbs    |  4 ++++
 .../main/admin/stack_upgrade/upgrade_wizard_view.js |  4 +++-
 .../admin/stack_upgrade/upgrade_wizard_view_test.js | 16 ++++++++++++++++
 4 files changed, 25 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/02bea547/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index bec2ca5..bda8228 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1852,6 +1852,8 @@ Em.I18n.translations = {
   'admin.stackUpgrade.failedHosts.options.first': "<b>Pause Upgrade</b>, delete the unhealthy hosts and return to the Upgrade Wizard to Proceed.",
   'admin.stackUpgrade.failedHosts.options.second': "Perform a <b>Downgrade</b>, which will revert all hosts to the previous stack version.",
   'admin.stackUpgrade.failedHosts.options.third': "Ignore these failures and <b>Proceed</b> for now (reconcile the failures later).",
+  'admin.stackUpgrade.failedHosts.isOutOfSync.options.first' : '<b>Pause Upgrade</b> and restart the component',
+  'admin.stackUpgrade.failedHosts.isOutOfSync.options.second' : '<b>Restart</b> the Ambari Agent',
   'admin.stackUpgrade.failedHosts.header': "Failed Hosts",
   'admin.stackUpgrade.failedHosts.subHeader': "Upgrade failed on {0} hosts",
   'admin.stackUpgrade.failedHosts.details': "Open Details",

http://git-wip-us.apache.org/repos/asf/ambari/blob/02bea547/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_wizard.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_wizard.hbs b/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_wizard.hbs
index 6d06f91..cfbbb7a 100644
--- a/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_wizard.hbs
+++ b/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_wizard.hbs
@@ -180,6 +180,10 @@
                 <p>
                   {{t admin.stackUpgrade.failedHosts.options}}
                 <ul>
+                  {{#if view.isOutOfSync}}
+                    <li>{{t admin.stackUpgrade.failedHosts.isOutOfSync.options.first}}</li>
+                    <li>{{t admin.stackUpgrade.failedHosts.isOutOfSync.options.second}}</li>
+                  {{/if}}
                   <li>{{t admin.stackUpgrade.failedHosts.options.first}}</li>
                   {{#if view.isDowngradeAvailable}}
                     <li>{{t admin.stackUpgrade.failedHosts.options.second}}</li>

http://git-wip-us.apache.org/repos/asf/ambari/blob/02bea547/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
index 10e34ab..a5e7730 100644
--- a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
+++ b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
@@ -192,7 +192,9 @@ App.upgradeWizardView = Em.View.extend({
    */
   isSlaveComponentFailuresItem: function () {
     var item = this.get('activeGroup.upgradeItems') && this.get('activeGroup.upgradeItems').findProperty('context', this.get("controller.slaveFailuresContext"));
-    return item && ['HOLDING', 'HOLDING_FAILED'].contains(item.get('status'));
+    var status = item && item.get('status');
+    this.set('isOutOfSync', status === 'OUT_OF_SYNC');
+    return ['HOLDING', 'HOLDING_FAILED', 'OUT_OF_SYNC'].contains(status);
   }.property('activeGroup.upgradeItems.@each.status', 'activeGroup.upgradeItems.@each.context'),
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/02bea547/ambari-web/test/views/main/admin/stack_upgrade/upgrade_wizard_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_wizard_view_test.js b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_wizard_view_test.js
index 7ae785c..8ad711e 100644
--- a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_wizard_view_test.js
+++ b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_wizard_view_test.js
@@ -868,6 +868,22 @@ describe('App.upgradeWizardView', function () {
       expect(view.get('controller.areSlaveComponentFailuresHostsLoaded')).to.be.true;
     });
   });
+  it("isSlaveComponentFailuresItem must be true when status is OUT_OF_SYNC", function () {
+    view.reopen({
+      activeStatuses: ['OUT_OF_SYNC'],
+      upgradeGroups: [Em.Object.create({
+        status: 'OUT_OF_SYNC'
+      })]
+    });
+    view.propertyDidChange('activeGroup');
+    view.set('activeGroup.upgradeItems', [Em.Object.create({
+      context: view.get("controller.slaveFailuresContext"),
+      status: 'OUT_OF_SYNC'
+    })]);
+
+    expect(view.get('isSlaveComponentFailuresItem')).to.be.true;
+    expect(view.get('isOutOfSync')).to.be.true;
+  });
 
   describe("#getServiceCheckItem()", function() {
     beforeEach(function () {


[17/38] ambari git commit: AMBARI-21810. Create Utility Script to support Solr Collection Data Retention/Purging/Archiving (mgergely)

Posted by lp...@apache.org.
AMBARI-21810. Create Utility Script to support Solr Collection Data Retention/Purging/Archiving (mgergely)

Change-Id: Ie25e5187e6e96d5b14267491fb7a9a992529b405


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/153d0da7
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/153d0da7
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/153d0da7

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 153d0da771d1ad523ad90b487fa185aa2bf0d52d
Parents: 2a6dd58
Author: Miklos Gergely <mg...@hortonworks.com>
Authored: Wed Sep 13 16:46:02 2017 +0200
Committer: Miklos Gergely <mg...@hortonworks.com>
Committed: Wed Sep 13 16:46:02 2017 +0200

----------------------------------------------------------------------
 ambari-infra/ambari-infra-solr-client/build.xml |   1 +
 ambari-infra/ambari-infra-solr-client/pom.xml   |   5 +
 .../apache/ambari/infra/solr/S3Uploader.java    |  64 ++
 .../src/main/python/solrDataManager.py          | 715 +++++++++++++++++++
 4 files changed, 785 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/153d0da7/ambari-infra/ambari-infra-solr-client/build.xml
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-solr-client/build.xml b/ambari-infra/ambari-infra-solr-client/build.xml
index 9b8b6cc..25ff0cb 100644
--- a/ambari-infra/ambari-infra-solr-client/build.xml
+++ b/ambari-infra/ambari-infra-solr-client/build.xml
@@ -36,6 +36,7 @@
     <copy todir="target/package" includeEmptyDirs="no">
       <fileset file="src/main/resources/solrCloudCli.sh"/>
       <fileset file="src/main/resources/solrIndexHelper.sh"/>
+      <fileset file="src/main/python/solrDataManager.py"/>
     </copy>
     <copy todir="target/package" includeEmptyDirs="no">
       <fileset file="src/main/resources/log4j.properties"/>

http://git-wip-us.apache.org/repos/asf/ambari/blob/153d0da7/ambari-infra/ambari-infra-solr-client/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-solr-client/pom.xml b/ambari-infra/ambari-infra-solr-client/pom.xml
index 3818aba..0d32374 100644
--- a/ambari-infra/ambari-infra-solr-client/pom.xml
+++ b/ambari-infra/ambari-infra-solr-client/pom.xml
@@ -82,6 +82,11 @@
       <artifactId>log4j</artifactId>
     </dependency>
     <dependency>
+      <groupId>com.amazonaws</groupId>
+      <artifactId>aws-java-sdk-s3</artifactId>
+      <version>1.11.5</version>
+    </dependency>
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/ambari/blob/153d0da7/ambari-infra/ambari-infra-solr-client/src/main/java/org/apache/ambari/infra/solr/S3Uploader.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-solr-client/src/main/java/org/apache/ambari/infra/solr/S3Uploader.java b/ambari-infra/ambari-infra-solr-client/src/main/java/org/apache/ambari/infra/solr/S3Uploader.java
new file mode 100644
index 0000000..60b4e0a
--- /dev/null
+++ b/ambari-infra/ambari-infra-solr-client/src/main/java/org/apache/ambari/infra/solr/S3Uploader.java
@@ -0,0 +1,64 @@
+/*
+ * 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.infra.solr;
+
+import java.io.File;
+
+import org.apache.commons.io.FileUtils;
+
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.services.s3.AmazonS3Client;
+
+/**
+ * Uploads a file to S3, meant to be used by solrDataManager.py
+ */
+public class S3Uploader {
+  public static void main(String[] args) {
+    try {
+      String keyFilePath = args[0];
+      String bucketName = args[1];
+      String keyPrefix = args[2];
+      String filePath = args[3];
+
+      String keyFileContent = FileUtils.readFileToString(new File(keyFilePath)).trim();
+      String[] keys = keyFileContent.split(",");
+      String accessKey = keys[0];
+      String secretKey = keys[1];
+
+      BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
+      AmazonS3Client client = new AmazonS3Client(credentials);
+
+      File file = new File(filePath);
+      String key = keyPrefix + file.getName();
+      
+      if (client.doesObjectExist(bucketName, key)) {
+        System.out.println("Object '" + key + "' already exists");
+        System.exit(0);
+      }
+
+      client.putObject(bucketName, key, file);
+    } catch (Exception e) {
+      e.printStackTrace(System.err);
+      System.exit(1);
+    }
+    
+    System.exit(0);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/153d0da7/ambari-infra/ambari-infra-solr-client/src/main/python/solrDataManager.py
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-solr-client/src/main/python/solrDataManager.py b/ambari-infra/ambari-infra-solr-client/src/main/python/solrDataManager.py
new file mode 100644
index 0000000..d17aec7
--- /dev/null
+++ b/ambari-infra/ambari-infra-solr-client/src/main/python/solrDataManager.py
@@ -0,0 +1,715 @@
+#!/usr/bin/python
+
+'''
+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.
+'''
+
+import hashlib
+import json
+import logging
+import optparse
+import os
+import time
+import signal
+import sys
+
+from datetime import datetime, timedelta
+from subprocess import call, Popen, PIPE
+from urllib import quote, unquote
+from zipfile import ZipFile, ZIP_DEFLATED
+import tarfile
+
+VERSION = "1.0"
+
+logger = logging.getLogger()
+handler = logging.StreamHandler()
+formatter = logging.Formatter("%(asctime)s - %(message)s")
+handler.setFormatter(formatter)
+logger.addHandler(handler)
+verbose = False
+
+def parse_arguments():
+  parser = optparse.OptionParser("usage: %prog [options]", version="Solr Data Manager {0}".format(VERSION))
+
+  parser.add_option("-m", "--mode", dest="mode", type="string", help="delete | save")
+  parser.add_option("-s", "--solr-url", dest="solr_url", type="string", help="the url of the solr server including the port")
+  parser.add_option("-c", "--collection", dest="collection", type="string", help="the name of the solr collection")
+  parser.add_option("-f", "--filter-field", dest="filter_field", type="string", help="the name of the field to filter on")
+  parser.add_option("-r", "--read-block-size", dest="read_block_size", type="int", help="block size to use for reading from solr",
+                    default=1000)
+  parser.add_option("-w", "--write-block-size", dest="write_block_size", type="int", help="number of records in the output files",
+                    default=100000)
+  parser.add_option("-i", "--id-field", dest="id_field", type="string", help="the name of the id field", default="id")
+
+  end_group = optparse.OptionGroup(parser, "specifying the end of the range")
+  end_group.add_option("-e", "--end", dest="end", type="string", help="end of the range")
+  end_group.add_option("-d", "--days", dest="days", type="int", help="number of days to keep")
+  parser.add_option_group(end_group)
+
+  parser.add_option("-o", "--date-format", dest="date_format", type="string", help="the date format to use for --days",
+                    default="%Y-%m-%dT%H:%M:%S.%fZ")
+  
+  parser.add_option("-q", "--additional-filter", dest="additional_filter", type="string", help="additional solr filter")
+  parser.add_option("--name", dest="name", type="string", help="name included in result files")
+  
+  parser.add_option("-g", "--ignore-unfinished-uploading", dest="ignore_unfinished_uploading", action="store_true", default=False)
+  
+  parser.add_option("-j", "--line-delimited", dest="line_delimited", help="line delmited json output", action="store_true", default=False)
+  parser.add_option("-z", "--compression", dest="compression", help="none | tar.gz | tar.bz2 | zip", default="tar.gz")
+  
+  parser.add_option("-k", "--solr-keytab", dest="solr_keytab", type="string", help="the keytab for a kerberized solr")
+  parser.add_option("-n", "--solr-principal", dest="solr_principal", type="string", help="the principal for a kerberized solr")
+  
+  parser.add_option("-a", "--hdfs-keytab", dest="hdfs_keytab", type="string", help="the keytab for a kerberized hdfs")
+  parser.add_option("-l", "--hdfs-principal", dest="hdfs_principal", type="string", help="the principal for a kerberized hdfs")
+  
+  parser.add_option("-u", "--hdfs-user", dest="hdfs_user", type="string", help="the user for accessing hdfs")
+  parser.add_option("-p", "--hdfs-path", dest="hdfs_path", type="string", help="the hdfs path to upload to")
+  
+  parser.add_option("-t", "--key-file-path", dest="key_file_path", type="string", help="the file that contains S3 <accessKey>,<secretKey>")
+  parser.add_option("-b", "--bucket", dest="bucket", type="string", help="the bucket name for S3 upload")
+  parser.add_option("-y", "--key-prefix", dest="key_prefix", type="string", help="the key prefix for S3 upload")
+  
+  parser.add_option("-x", "--local-path", dest="local_path", type="string", help="the local path to save the files to")
+  
+  parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False)
+  
+  (options, args) = parser.parse_args()
+  
+  for r in ["mode", "solr_url", "collection", "filter_field"]:
+    if options.__dict__[r] is None:
+      print "argument '{0}' is mandatory".format(r)
+      parser.print_help()
+      sys.exit()
+  
+  mode_values = ["delete", "save"]
+  if options.mode not in mode_values:
+    print "mode must be one of {0}".format(" | ".join(mode_values))
+    parser.print_help()
+    sys.exit()
+
+  if options.mode == "delete":
+    for r in ["name", "compression", "hdfs_keytab", "hdfs_principal", "hdfs_user", "hdfs_path", "key_file_path", "bucket", "key_prefix", "local_path"]:
+      if options.__dict__[r] is not None:
+        print "argument '{0}' may not be specified in delete mode".format(r)
+        parser.print_help()
+        sys.exit()
+
+  if options.__dict__["end"] is None and options.__dict__["days"] is None or \
+     options.__dict__["end"] is not None and options.__dict__["days"] is not None:
+    print "exactly one of 'end' or 'days' must be specfied"
+    parser.print_help()
+    sys.exit()
+
+  is_any_solr_kerberos_property = options.__dict__["solr_keytab"] is not None or options.__dict__["solr_principal"] is not None
+  is_all_solr_kerberos_property = options.__dict__["solr_keytab"] is not None and options.__dict__["solr_principal"] is not None
+  if is_any_solr_kerberos_property and not is_all_solr_kerberos_property:
+    print "either both 'solr-keytab' and 'solr-principal' must be specfied, or neither of them"
+    parser.print_help()
+    sys.exit()
+
+  compression_values = ["none", "tar.gz", "tar.bz2", "zip"]
+  if options.compression not in compression_values:
+    print "compression must be one of {0}".format(" | ".join(compression_values))
+    parser.print_help()
+    sys.exit()
+
+  is_any_hdfs_kerberos_property = options.__dict__["hdfs_keytab"] is not None or options.__dict__["hdfs_principal"] is not None
+  is_all_hdfs_kerberos_property = options.__dict__["hdfs_keytab"] is not None and options.__dict__["hdfs_principal"] is not None
+  if is_any_hdfs_kerberos_property and not is_all_hdfs_kerberos_property:
+    print "either both 'hdfs_keytab' and 'hdfs_principal' must be specfied, or neither of them"
+    parser.print_help()
+    sys.exit()
+
+  is_any_hdfs_property = options.__dict__["hdfs_user"] is not None or options.__dict__["hdfs_path"] is not None
+  is_all_hdfs_property = options.__dict__["hdfs_user"] is not None and options.__dict__["hdfs_path"] is not None
+  if is_any_hdfs_property and not is_all_hdfs_property:
+    print "either both 'hdfs_user' and 'hdfs_path' must be specfied, or neither of them"
+    parser.print_help()
+    sys.exit()
+
+  is_any_s3_property = options.__dict__["key_file_path"] is not None or options.__dict__["bucket"] is not None or \
+                       options.__dict__["key_prefix"] is not None
+  is_all_s3_property = options.__dict__["key_file_path"] is not None and options.__dict__["bucket"] is not None and \
+                       options.__dict__["key_prefix"] is not None
+  if is_any_s3_property and not is_all_s3_property:
+    print "either all the S3 arguments ('key_file_path', 'bucket', 'key_prefix') must be specfied, or none of them"
+    parser.print_help()
+    sys.exit()
+
+  if options.mode == "save":
+    count = (1 if is_any_hdfs_property else 0) + (1 if is_any_s3_property else 0) + \
+            (1 if options.__dict__["local_path"] is not None else 0)
+    if count != 1:
+      print "exactly one of the HDFS arguments ('hdfs_user', 'hdfs_path') or the S3 arguments ('key_file_path', 'bucket', 'key_prefix') or the 'local_path' argument must be specified"
+      parser.print_help()
+      sys.exit()
+
+  if options.__dict__["hdfs_keytab"] is not None and options.__dict__["hdfs_user"] is None:
+    print "HDFS kerberos keytab and principal may only be specified if the upload target is HDFS"
+    parser.print_help()
+    sys.exit()
+
+  print("You are running Solr Data Manager {0} with arguments:".format(VERSION))
+  print("  mode: " + options.mode)
+  print("  solr-url: " + options.solr_url)
+  print("  collection: " + options.collection)
+  print("  filter-field: " + options.filter_field)
+  if options.mode == "save":
+    print("  id-field: " + options.id_field)
+  if options.__dict__["end"] is not None:
+    print("  end: " + options.end)
+  else:
+    print("  days: " + str(options.days))
+    print("  date-format: " + options.date_format)
+  if options.__dict__["additional_filter"] is not None:
+    print("  additional-filter: " + str(options.additional_filter))
+  if options.__dict__["name"] is not None:
+    print("  name: " + str(options.name))
+  if options.mode == "save":
+    print("  read-block-size: " + str(options.read_block_size))
+    print("  write-block-size: " + str(options.write_block_size))
+    print("  ignore-unfinished-uploading: " + str(options.ignore_unfinished_uploading))
+  if (options.__dict__["solr_keytab"] is not None):
+    print("  solr-keytab: " + options.solr_keytab)
+    print("  solr-principal: " + options.solr_principal)
+  if options.mode == "save":
+    print("  line-delimited: " + str(options.line_delimited))
+    print("  compression: " + options.compression)
+  if (options.__dict__["hdfs_keytab"] is not None):
+    print("  hdfs-keytab: " + options.hdfs_keytab)
+    print("  hdfs-principal: " + options.hdfs_principal)
+  if (options.__dict__["hdfs_user"] is not None):
+    print("  hdfs-user: " + options.hdfs_user)
+    print("  hdfs-path: " + options.hdfs_path)
+  if (options.__dict__["key_file_path"] is not None):
+    print("  key-file-path: " + options.key_file_path)
+    print("  bucket: " + options.bucket)
+    print("  key-prefix: " + options.key_prefix)
+  if (options.__dict__["local_path"] is not None):
+    print("  local-path: " + options.local_path)
+  print("  verbose: " + str(options.verbose))
+  print
+
+  if options.__dict__["additional_filter"] is not None and options.__dict__["name"] is None:
+    go = False
+    while not go:
+      sys.stdout.write("It is recommended to set --name in case of any additional filter is set.\n")
+      sys.stdout.write("Are you sure that you want to proceed without a name (yes/no)? ")
+      choice = raw_input().lower()
+      if choice in ['yes', 'ye', 'y']:
+        go = True
+      elif choice in ['no', 'n']:
+        sys.exit()
+
+  return options
+
+def set_log_level():
+  if verbose:
+    logger.setLevel(logging.DEBUG)
+  else:
+    logger.setLevel(logging.INFO)
+
+def get_end(options):
+  if options.end:
+    return options.end
+  else:
+    d = datetime.now() - timedelta(days=options.days)
+    end = d.strftime(options.date_format)
+    logger.info("The end date will be: %s", end)
+    return end
+
+def delete(solr_url, collection, filter_field, end, solr_keytab, solr_principal):
+  logger.info("Deleting data where %s <= %s", filter_field, end)
+  solr_kinit_command = None
+  if solr_keytab:
+    solr_kinit_command = "kinit -kt {0} {1}".format(solr_keytab, solr_principal)
+    curl_prefix = "curl -k --negotiate -u : "
+  else:
+    curl_prefix = "curl -k"
+  
+  delete_range = "{0}:[*+TO+\"{1}\"]".format(filter_field, end)
+  delete_query = quote("{0}:[*+TO+\"{1}\"]".format(filter_field, end), safe="/+\"*")
+  delete_command = "{0}/{1}/update?stream.body=<delete><query>{2}</query></delete>&commit=true&wt=json" \
+    .format(solr_url, collection, delete_query)
+  
+  query_solr(solr_kinit_command, delete_command, "{0} {1}".format(curl_prefix, delete_command), "Deleting")
+
+def save(solr_url, collection, filter_field, id_field, range_end, read_block_size, write_block_size,
+         ignore_unfinished_uploading, additional_filter, name, solr_keytab, solr_principal, line_delimited,
+         compression, hdfs_keytab, hdfs_principal, hdfs_user, hdfs_path, key_file_path, bucket, key_prefix, local_path):
+  solr_kinit_command = None
+  if solr_keytab:
+    solr_kinit_command = "kinit -kt {0} {1}".format(solr_keytab, solr_principal)
+    curl_prefix = "curl -k --negotiate -u : "
+  else:
+    curl_prefix = "curl -k"
+  
+  hdfs_kinit_command = None
+  if hdfs_keytab:
+    hdfs_kinit_command = "sudo -u {0} kinit -kt {1} {2}".format(hdfs_user, hdfs_keytab, hdfs_principal)
+  
+  if options.hdfs_path:
+    ensure_hdfs_path(hdfs_kinit_command, hdfs_user, hdfs_path)
+
+  working_dir = get_working_dir(solr_url, collection)
+  handle_unfinished_uploading(solr_kinit_command, hdfs_kinit_command, curl_prefix, working_dir, ignore_unfinished_uploading)
+  save_data(solr_kinit_command, hdfs_kinit_command, curl_prefix, solr_url, collection, filter_field, id_field, range_end,
+            read_block_size, write_block_size, working_dir, additional_filter, name, line_delimited, compression,
+            hdfs_user, hdfs_path, key_file_path, bucket, key_prefix, local_path)
+
+def ensure_hdfs_path(hdfs_kinit_command, hdfs_user, hdfs_path):
+  if hdfs_kinit_command:
+    run_kinit(hdfs_kinit_command, "HDFS")
+  
+  try:
+    hdfs_create_dir_command = "sudo -u {0} hadoop fs -mkdir -p {1}".format(hdfs_user, hdfs_path)
+    logger.debug("Ensuring that the HDFS path %s exists:\n%s", hdfs_path, hdfs_create_dir_command)
+    result = call(hdfs_create_dir_command.split())
+  except Exception as e:
+    print
+    logger.warn("Could not execute hdfs ensure dir command:\n%s", hdfs_create_dir_command)
+    logger.warn(str(e))
+    sys.exit()
+  
+  if result != 0:
+    print
+    logger.warn("Could not ensure HDFS dir command:\n%s", hdfs_create_dir_command)
+    logger.warn(str(err))
+    sys.exit()
+
+def get_working_dir(solr_url, collection):
+  md5 = hashlib.md5()
+  md5.update(solr_url)
+  md5.update(collection)
+  hash = md5.hexdigest()
+  working_dir = "/tmp/solrDataManager/{0}".format(hash)
+  
+  if not(os.path.isdir(working_dir)):
+    os.makedirs(working_dir)
+  
+  logger.debug("Working directory is %s", working_dir)
+  return working_dir
+
+def handle_unfinished_uploading(solr_kinit_command, hdfs_kinit_command, curl_prefix, working_dir, ignore_unfinished_uploading):
+  command_json_path = "{0}/command.json".format(working_dir)
+  if os.path.isfile(command_json_path):
+    with open(command_json_path) as command_file:
+      command = json.load(command_file)
+    
+    if "upload" in command.keys() and ignore_unfinished_uploading:
+      logger.info("Ignoring unfinished uploading left by previous run")
+      os.remove(command_json_path)
+      return
+    
+    if "upload" in command.keys():
+      logger.info("Previous run has left unfinished uploading")
+      logger.info("You may try to run the program with '-g' or '--ignore-unfinished-uploading' to ignore it if it keeps on failing")
+      
+      if command["upload"]["type"] == "hdfs":
+        upload_file_hdfs(hdfs_kinit_command, command["upload"]["command"], command["upload"]["upload_file_path"],
+                         command["upload"]["hdfs_path"], command["upload"]["hdfs_user"])
+      elif command["upload"]["type"] == "s3":
+        upload_file_s3(command["upload"]["command"], command["upload"]["upload_file_path"], command["upload"]["bucket"],
+                       command["upload"]["key_prefix"])
+      elif command["upload"]["type"] == "local":
+        upload_file_local(command["upload"]["command"], command["upload"]["upload_file_path"], command["upload"]["local_path"])
+      else:
+        logger.warn("Unknown upload type: %s", command["upload"]["type"])
+        sys.exit()
+    
+    if "delete" in command.keys():
+      delete_data(solr_kinit_command, curl_prefix, command["delete"]["command"], command["delete"]["collection"],
+                  command["delete"]["filter_field"], command["delete"]["id_field"], command["delete"]["prev_lot_end_value"],
+                  command["delete"]["prev_lot_end_id"])
+    
+    os.remove(command_json_path)
+
+def save_data(solr_kinit_command, hdfs_kinit_command, curl_prefix, solr_url, collection, filter_field, id_field,
+              range_end, read_block_size, write_block_size, working_dir, additional_filter, name, line_delimited,
+              compression, hdfs_user, hdfs_path, key_file_path, bucket, key_prefix, local_path):
+  logger.info("Starting to save data")
+  
+  tmp_file_path = "{0}/tmp.json".format(working_dir)
+  true = True # needed to be able to eval 'true' in the returned json
+  
+  prev_lot_end_value = None
+  prev_lot_end_id = None
+  
+  if additional_filter:
+    q = quote("{0}+AND+{1}:[*+TO+\"{2}\"]".format(additional_filter, filter_field, range_end), safe="/+\"*")
+  else:
+    q = quote("{0}:[*+TO+\"{1}\"]".format(filter_field, range_end), safe="/+\"*")
+  
+  sort = quote("{0}+asc,{1}+asc".format(filter_field, id_field), safe="/+\"*")
+  solr_query_url_prefix = "{0}/{1}/select?q={2}&sort={3}&rows={4}&wt=json".format(solr_url, collection, q, sort, read_block_size)
+  
+  done = False
+  total_records = 0
+  while not done:
+    results = create_block(tmp_file_path, solr_kinit_command, curl_prefix, solr_query_url_prefix, filter_field,
+                           id_field, range_end, write_block_size, prev_lot_end_value, prev_lot_end_id,
+                           line_delimited)
+    done = results[0]
+    records = results[1]
+    prev_lot_end_value = results[2]
+    prev_lot_end_id = results[3]
+    
+    if records > 0:
+      upload_block(solr_kinit_command, hdfs_kinit_command, curl_prefix, solr_url, collection, filter_field, id_field,
+                   working_dir, tmp_file_path, name, prev_lot_end_value, prev_lot_end_id, hdfs_user, hdfs_path,
+                   key_file_path, bucket, key_prefix, local_path, compression)
+      total_records += records
+      logger.info("A total of %d records are saved", total_records)
+
+def create_block(tmp_file_path, solr_kinit_command, curl_prefix, solr_query_url_prefix, filter_field, id_field, range_end,
+                 write_block_size, prev_lot_end_value, prev_lot_end_id, line_delimited):
+  if os.path.exists(tmp_file_path):
+    os.remove(tmp_file_path)
+  tmp_file = open(tmp_file_path, 'w')
+  logger.debug("Created tmp file %s", tmp_file_path)
+  
+  init_file(tmp_file, line_delimited)
+  records = 0
+  done = False
+  while records < write_block_size:
+    if prev_lot_end_value:
+      fq_prev_end_rest = "({0}:\"{1}\"+AND+{2}:{{\"{3}\"+TO+*])".format(filter_field, prev_lot_end_value, id_field,
+                                                                        prev_lot_end_id)
+      fq_new = "{0}:{{\"{1}\"+TO+\"{2}\"]".format(filter_field, prev_lot_end_value, range_end)
+      fq = "{0}+OR+{1}".format(fq_prev_end_rest, fq_new)
+    else:
+      fq = "{0}:[*+TO+\"{1}\"]".format(filter_field, range_end)
+
+    url = "{0}&fq={1}".format(solr_query_url_prefix, quote(fq, safe="/+\"*"))
+    curl_command = "{0} {1}".format(curl_prefix, url)
+    
+    rsp = query_solr(solr_kinit_command, url, curl_command, "Obtaining")
+    
+    if rsp['response']['numFound'] == 0:
+      done = True
+      break
+
+    for doc in rsp['response']['docs']:
+      last_doc = doc
+      add_line(tmp_file, doc, line_delimited, records)
+      records += 1
+      if records == write_block_size:
+        break
+
+    prev_lot_end_value = last_doc[filter_field]
+    prev_lot_end_id = last_doc[id_field]
+    sys.stdout.write("\r{0} records are written".format(records))
+    sys.stdout.flush()
+    if verbose and records < write_block_size:
+      print
+      logger.debug("Collecting next lot of data")
+
+  finish_file(tmp_file, line_delimited)
+  sys.stdout.write("\n")
+  logger.debug("Finished data collection")
+  return [done, records, prev_lot_end_value, prev_lot_end_id]
+
+def init_file(tmp_file, line_delimited):
+  if not line_delimited:
+    tmp_file.write("{\n")
+
+def add_line(tmp_file, doc, line_delimited, records):
+  if records > 0:
+    if line_delimited:
+      tmp_file.write("\n")
+    else:
+      tmp_file.write(",\n")
+    
+  tmp_file.write(json.dumps(doc))
+
+def finish_file(tmp_file, line_delimited):
+  if not line_delimited:
+    tmp_file.write("\n}")
+
+def upload_block(solr_kinit_command, hdfs_kinit_command, curl_prefix, solr_url, collection, filter_field, id_field,
+                 working_dir, tmp_file_path, name, prev_lot_end_value, prev_lot_end_id, hdfs_user, hdfs_path,
+                 key_file_path, bucket, key_prefix, local_path, compression):
+  if name:
+    file_name = "{0}_-_{1}_-_{2}_-_{3}".format(collection, name, prev_lot_end_value, prev_lot_end_id).replace(':', '_')
+  else:
+    file_name = "{0}_-_{1}_-_{2}".format(collection, prev_lot_end_value, prev_lot_end_id).replace(':', '_')
+  
+  upload_file_path = compress_file(working_dir, tmp_file_path, file_name, compression)
+  
+  upload_command = create_command_file(True, working_dir, upload_file_path, solr_url, collection, filter_field, id_field,
+                                       prev_lot_end_value, prev_lot_end_id, hdfs_user, hdfs_path, key_file_path, bucket,
+                                       key_prefix, local_path)
+  if hdfs_user:
+    upload_file_hdfs(hdfs_kinit_command, upload_command, upload_file_path, hdfs_path, hdfs_user)
+  elif key_file_path:
+    upload_file_s3(upload_command, upload_file_path, bucket, key_prefix)
+  elif local_path:
+    upload_file_local(upload_command, upload_file_path, local_path)
+  else:
+    logger.warn("Unknown upload destination")
+    sys.exit()
+  
+  delete_command = create_command_file(False, working_dir, upload_file_path, solr_url, collection, filter_field, id_field,
+                                       prev_lot_end_value, prev_lot_end_id, None, None, None, None, None, None)
+  delete_data(solr_kinit_command, curl_prefix, delete_command, collection, filter_field, id_field, prev_lot_end_value, prev_lot_end_id)
+  
+  os.remove("{0}/command.json".format(working_dir))
+
+def compress_file(working_dir, tmp_file_path, file_name, compression):
+  if compression == "none":
+    upload_file_path = "{0}/{1}.json".format(working_dir, file_name)
+    os.rename(tmp_file_path, upload_file_path)
+  elif compression == "tar.gz":
+    upload_file_path = "{0}/{1}.tar.gz".format(working_dir, file_name)
+    zipped_file_name = "{0}.json".format(file_name)
+    tar = tarfile.open(upload_file_path, mode="w:gz")
+    try:
+      tar.add(tmp_file_path, arcname=zipped_file_name)
+    finally:
+      tar.close()
+  elif compression == "tar.bz2":
+    upload_file_path = "{0}/{1}.tar.bz2".format(working_dir, file_name)
+    zipped_file_name = "{0}.json".format(file_name)
+    tar = tarfile.open(upload_file_path, mode="w:bz2")
+    try:
+      tar.add(tmp_file_path, arcname=zipped_file_name)
+    finally:
+      tar.close()
+  elif compression == "zip":
+    upload_file_path = "{0}/{1}.zip".format(working_dir, file_name)
+    zipped_file_name = "{0}.json".format(file_name)
+    zip = ZipFile(upload_file_path, 'w')
+    zip.write(tmp_file_path, zipped_file_name, ZIP_DEFLATED)
+    logger.info("Created file %s", zipped_file_name)
+  else:
+    logger.warn("Unknown compression type")
+    sys.exit()
+  
+  return upload_file_path
+
+def create_command_file(upload, working_dir, upload_file_path, solr_url, collection, filter_field, id_field, prev_lot_end_value,
+                        prev_lot_end_id, hdfs_user, hdfs_path, key_file_path, bucket, key_prefix, local_path):
+  commands = {}
+  
+  if upload:
+    logger.debug("Creating command file with upload and delete instructions in case of an interruption")
+  else:
+    logger.debug("Creating command file with delete instructions in case of an interruption")
+  
+  if upload:
+    if hdfs_path:
+      upload_command = "sudo -u {0} hadoop fs -put {1} {2}".format(hdfs_user, upload_file_path, hdfs_path)
+      upload_command_data = {}
+      upload_command_data["type"] = "hdfs"
+      upload_command_data["command"] = upload_command
+      upload_command_data["upload_file_path"] = upload_file_path
+      upload_command_data["hdfs_path"] = hdfs_path
+      upload_command_data["hdfs_user"] = hdfs_user
+      commands["upload"] = upload_command_data
+    elif key_file_path:
+      upload_command = "java -cp {0}/libs/* org.apache.ambari.infra.solr.S3Uploader {1} {2} {3} {4}".format( \
+          os.path.dirname(os.path.realpath(__file__)), key_file_path, bucket, key_prefix, upload_file_path)
+      upload_command_data = {}
+      upload_command_data["type"] = "s3"
+      upload_command_data["command"] = upload_command
+      upload_command_data["upload_file_path"] = upload_file_path
+      upload_command_data["bucket"] = bucket
+      upload_command_data["key_prefix"] = key_prefix
+      commands["upload"] = upload_command_data
+    elif local_path:
+      upload_command = "mv {0} {1}".format(upload_file_path, local_path)
+      upload_command_data = {}
+      upload_command_data["type"] = "local"
+      upload_command_data["command"] = upload_command
+      upload_command_data["upload_file_path"] = upload_file_path
+      upload_command_data["local_path"] = local_path
+      commands["upload"] = upload_command_data
+    else:
+      logger.warn("Unknown upload destination")
+      sys.exit()
+
+  
+  delete_prev = "{0}:[*+TO+\"{1}\"]".format(filter_field, prev_lot_end_value)
+  delete_last = "({0}:\"{1}\"+AND+{2}:[*+TO+\"{3}\"])".format(filter_field, prev_lot_end_value, id_field, prev_lot_end_id)
+  delete_query = quote("{0}+OR+{1}".format(delete_prev, delete_last), safe="/+\"*")
+  delete_command = "{0}/{1}/update?stream.body=<delete><query>{2}</query></delete>&commit=true&wt=json" \
+    .format(solr_url, collection, delete_query)
+  delete_command_data = {}
+  delete_command_data["command"] = delete_command
+  delete_command_data["collection"] = collection
+  delete_command_data["filter_field"] = filter_field
+  delete_command_data["id_field"] = id_field
+  delete_command_data["prev_lot_end_value"] = prev_lot_end_value
+  delete_command_data["prev_lot_end_id"] = prev_lot_end_id
+  commands["delete"] = delete_command_data
+  
+  command_file_path = "{0}/command.json".format(working_dir)
+  command_file_path_tmp = "{0}.tmp".format(command_file_path)
+  cft = open(command_file_path_tmp, 'w')
+  cft.write(json.dumps(commands, indent=4))
+  os.rename(command_file_path_tmp, command_file_path)
+  
+  logger.debug("Command file %s was created", command_file_path)
+  
+  if upload:
+    return upload_command
+  else:
+    return delete_command
+
+def upload_file_hdfs(hdfs_kinit_command, upload_command, upload_file_path, hdfs_path, hdfs_user):
+  if hdfs_kinit_command:
+    run_kinit(hdfs_kinit_command, "HDFS")
+  
+  try:
+    hdfs_file_exists_command = "sudo -u {0} hadoop fs -test -e {1}".format(hdfs_user, hdfs_path + os.path.basename(upload_file_path))
+    logger.debug("Checking if file already exists on hdfs:\n%s", hdfs_file_exists_command)
+    hdfs_file_exists = (0 == call(hdfs_file_exists_command.split()))
+  except Exception as e:
+    print
+    logger.warn("Could not execute command to check if file already exists on HDFS:\n%s", hdfs_file_exists_command)
+    logger.warn(str(e))
+    sys.exit()
+  
+  if os.path.isfile(upload_file_path) and not hdfs_file_exists:
+    try:
+      logger.debug("Uploading file to hdfs:\n%s", upload_command)
+      result = call(upload_command.split())
+    except Exception as e:
+      print
+      logger.warn("Could not execute command to upload file to HDFS:\n%s", upload_command)
+      logger.warn(str(e))
+      sys.exit()
+    
+    if result != 0:
+      logger.warn("Could not upload file to HDFS with command:\n%s", upload_command)
+      sys.exit()
+    
+    logger.info("File %s was uploaded to hdfs %s", os.path.basename(upload_file_path), hdfs_path)
+    os.remove(upload_file_path)
+
+def upload_file_s3(upload_command, upload_file_path, bucket, key_prefix):
+  if os.path.isfile(upload_file_path):
+    try:
+      logger.debug("Uploading file to s3:\n%s", upload_command)
+      result = call(upload_command.split())
+    except Exception as e:
+      print
+      logger.warn("Could not execute command to upload file to S3:\n%s", upload_command)
+      logger.warn(str(e))
+      sys.exit()
+
+    if result != 0:
+      logger.warn("Could not upload file to S3 with command:\n%s", upload_command)
+      sys.exit()
+
+    logger.info("File %s was uploaded to s3 bucket '%s', key '%s'", os.path.basename(upload_file_path), bucket,
+                key_prefix + os.path.basename(upload_file_path))
+    os.remove(upload_file_path)
+
+def upload_file_local(upload_command, upload_file_path, local_path):
+  if os.path.exists(local_path) and not os.path.isdir(local_path):
+    logger.warn("Local path %s exists, but not a directory, can not save there", local_path)
+  if not os.path.isdir(local_path):
+    os.mkdir(local_path)
+    logger.debug("Directory %s was created", local_path)
+  
+  try:
+    logger.debug("Moving file to local directory %s with command\n%s", local_path, upload_command)
+    call(upload_command.split())
+    logger.info("File %s was moved to local directory %s", os.path.basename(upload_file_path), local_path)
+  except Exception as e:
+    print
+    logger.warn("Could not execute move command command:\n%s", upload_command)
+    logger.warn(str(e))
+    sys.exit()
+
+def delete_data(solr_kinit_command, curl_prefix, delete_command, collection, filter_field, id_field, prev_lot_end_value,
+                prev_lot_end_id):
+  query_solr(solr_kinit_command, delete_command, "{0} {1}".format(curl_prefix, delete_command), "Deleting")
+  logger.info("Deleted data from collection %s where %s,%s < %s,%s", collection, filter_field, id_field, prev_lot_end_value,
+              prev_lot_end_id)
+
+def query_solr(solr_kinit_command, url, curl_command, action):
+  if solr_kinit_command:
+    run_kinit(solr_kinit_command, "Solr")
+
+  try:
+    logger.debug("%s data from solr:\n%s", action, curl_command)
+    process = Popen(curl_command.split(), stdin=PIPE, stdout=PIPE, stderr=PIPE)
+  except Exception as e:
+    print
+    logger.warn("Could not execute curl command:\n%s", curl_command)
+    logger.warn(str(e))
+    sys.exit()
+
+  out, err = process.communicate()
+  if process.returncode != 0:
+    print
+    logger.warn("Could not execute curl command:\n%s", curl_command)
+    logger.warn(str(err))
+    sys.exit()
+
+  rsp = eval(str(out))
+  if rsp["responseHeader"]["status"] != 0:
+    print
+    logger.warn("Could not execute solr query:\n%s", unquote(url))
+    logger.warn(rsp["error"]["msg"])
+    sys.exit()
+
+  return rsp
+
+def run_kinit(kinit_command, program):
+  try:
+    logger.debug("Running kinit for %s:\n%s", program, kinit_command)
+    result = call(kinit_command.split())
+  except Exception as e:
+    print
+    logger.warn("Could not execute %s kinit command:\n%s", program, kinit_command)
+    logger.warn(str(e))
+    sys.exit()
+  
+  if result != 0:
+    print
+    logger.warn("%s kinit command was not successful:\n%s", program, kinit_command)
+    sys.exit()
+
+if __name__ == '__main__':
+  try:
+    start_time = time.time()
+    
+    options = parse_arguments()
+    verbose = options.verbose
+    set_log_level()
+    
+    end = get_end(options)
+    
+    if options.mode == "delete":
+      delete(options.solr_url, options.collection, options.filter_field, end, options.solr_keytab, options.solr_principal)
+    elif options.mode == "save":
+      save(options.solr_url, options.collection, options.filter_field, options.id_field, end, options.read_block_size,
+           options.write_block_size, options.ignore_unfinished_uploading, options.additional_filter, options.name,
+           options.solr_keytab, options.solr_principal, options.line_delimited, options.compression,
+           options.hdfs_keytab, options.hdfs_principal, options.hdfs_user, options.hdfs_path, options.key_file_path,
+           options.bucket, options.key_prefix, options.local_path)
+    else:
+      logger.warn("Unknown mode: %s", options.mode)
+    
+    print("--- %s seconds ---" % (time.time() - start_time))
+  except KeyboardInterrupt:
+    print
+    sys.exit(128 + signal.SIGINT)


[20/38] ambari git commit: AMBARI-21942. Upgrade to IOP 4.2.5 from IOP 4.1 failed with combined Solr host names longer than item_text column size in table upgrade_item. (swagle)

Posted by lp...@apache.org.
AMBARI-21942. Upgrade to IOP 4.2.5 from IOP 4.1 failed with combined Solr host names longer than item_text column size in table upgrade_item. (swagle)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7a7d2320
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7a7d2320
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7a7d2320

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 7a7d2320a1ebf37e44b487dbf04de2a1c16761cd
Parents: 16cc3a6
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Wed Sep 13 10:19:10 2017 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Wed Sep 13 10:19:10 2017 -0700

----------------------------------------------------------------------
 .../apache/ambari/server/orm/DBAccessorImpl.java |  6 ++----
 .../server/orm/entities/UpgradeItemEntity.java   |  2 +-
 .../ambari/server/upgrade/UpgradeCatalog260.java | 19 +++++++++++++++++++
 .../main/resources/Ambari-DDL-Derby-CREATE.sql   |  2 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql   |  2 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql  |  2 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql     |  2 +-
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql  |  2 +-
 .../resources/Ambari-DDL-SQLServer-CREATE.sql    |  2 +-
 9 files changed, 28 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7a7d2320/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
index b137705..26670fc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
@@ -653,12 +653,10 @@ public class DBAccessorImpl implements DBAccessor {
   }
 
   @Override
-  public void alterColumn(String tableName, DBColumnInfo columnInfo)
-          throws SQLException {
+  public void alterColumn(String tableName, DBColumnInfo columnInfo) throws SQLException {
     //varchar extension only (derby limitation, but not too much for others),
     if (dbmsHelper.supportsColumnTypeChange()) {
-      String statement = dbmsHelper.getAlterColumnStatement(tableName,
-              columnInfo);
+      String statement = dbmsHelper.getAlterColumnStatement(tableName, columnInfo);
       executeQuery(statement);
     } else {
       //use addColumn: add_tmp-update-drop-rename for Derby

http://git-wip-us.apache.org/repos/asf/ambari/blob/7a7d2320/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeItemEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeItemEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeItemEntity.java
index 7f0408f..0c254ef 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeItemEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeItemEntity.java
@@ -76,7 +76,7 @@ public class UpgradeItemEntity {
   private String tasks = null;
 
   @Basic
-  @Column(name = "item_text", length = 1024)
+  @Column(name = "item_text")
   private String itemText = null;
 
   @Basic

http://git-wip-us.apache.org/repos/asf/ambari/blob/7a7d2320/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
index b17569e..79ff9e2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
@@ -31,6 +31,7 @@ import javax.persistence.EntityManager;
 import javax.persistence.Query;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.orm.dao.ArtifactDAO;
@@ -45,6 +46,7 @@ import org.apache.ambari.server.state.kerberos.KerberosDescriptorFactory;
 import org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor;
 import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
 import org.apache.commons.lang.StringUtils;
+import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -107,6 +109,7 @@ public class UpgradeCatalog260 extends AbstractUpgradeCatalog {
   public static final String FK_UPGRADE_FROM_REPO_ID = "FK_upgrade_from_repo_id";
   public static final String FK_UPGRADE_TO_REPO_ID = "FK_upgrade_to_repo_id";
   public static final String FK_UPGRADE_REPO_VERSION_ID = "FK_upgrade_repo_version_id";
+  public static final String UPGRADE_ITEM_ITEM_TEXT = "item_text";
 
   public static final String SERVICE_COMPONENT_HISTORY_TABLE = "servicecomponent_history";
   public static final String UPGRADE_HISTORY_TABLE = "upgrade_history";
@@ -181,6 +184,22 @@ public class UpgradeCatalog260 extends AbstractUpgradeCatalog {
     createUpgradeHistoryTable();
     updateRepositoryVersionTable();
     renameServiceDeletedColumn();
+    expandUpgradeItemItemTextColumn();
+  }
+
+  /**
+   * Expand item_text column of upgrade_item
+   */
+  private void expandUpgradeItemItemTextColumn() throws SQLException {
+    Configuration.DatabaseType databaseType = configuration.getDatabaseType();
+
+    if (Configuration.DatabaseType.MYSQL == databaseType) {
+      dbAccessor.alterColumn(UPGRADE_ITEM_TABLE, new DBAccessor.DBColumnInfo(
+        UPGRADE_ITEM_ITEM_TEXT, new FieldTypeDefinition("TEXT"), null));
+    } else {
+      dbAccessor.changeColumnType(UPGRADE_ITEM_TABLE, UPGRADE_ITEM_ITEM_TEXT,
+        String.class, char[].class);
+    }
   }
 
   private void renameServiceDeletedColumn() throws AmbariException, SQLException {

http://git-wip-us.apache.org/repos/asf/ambari/blob/7a7d2320/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
index e7359a7..74fff6c 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -843,7 +843,7 @@ CREATE TABLE upgrade_item (
   state VARCHAR(255) DEFAULT 'NONE' NOT NULL,
   hosts VARCHAR(3000),
   tasks VARCHAR(3000),
-  item_text VARCHAR(1024),
+  item_text VARCHAR(3000),
   CONSTRAINT PK_upgrade_item PRIMARY KEY (upgrade_item_id),
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );

http://git-wip-us.apache.org/repos/asf/ambari/blob/7a7d2320/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 c1e1953..beda848 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -860,7 +860,7 @@ CREATE TABLE upgrade_item (
   state VARCHAR(255) DEFAULT 'NONE' NOT NULL,
   hosts TEXT,
   tasks TEXT,
-  item_text VARCHAR(1024),
+  item_text TEXT,
   CONSTRAINT PK_upgrade_item PRIMARY KEY (upgrade_item_id),
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );

http://git-wip-us.apache.org/repos/asf/ambari/blob/7a7d2320/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 c0b2f0c..4f27dfb 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -839,7 +839,7 @@ CREATE TABLE upgrade_item (
   state VARCHAR2(255) DEFAULT 'NONE' NOT NULL,
   hosts CLOB,
   tasks CLOB,
-  item_text VARCHAR2(1024),
+  item_text CLOB,
   CONSTRAINT PK_upgrade_item PRIMARY KEY (upgrade_item_id),
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );

http://git-wip-us.apache.org/repos/asf/ambari/blob/7a7d2320/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 90cdbfe..355ee80 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -841,7 +841,7 @@ CREATE TABLE upgrade_item (
   state VARCHAR(255) DEFAULT 'NONE' NOT NULL,
   hosts TEXT,
   tasks TEXT,
-  item_text VARCHAR(1024),
+  item_text TEXT,
   CONSTRAINT PK_upgrade_item PRIMARY KEY (upgrade_item_id),
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );

http://git-wip-us.apache.org/repos/asf/ambari/blob/7a7d2320/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index 7f39535..76d4441 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -837,7 +837,7 @@ CREATE TABLE upgrade_item (
   state VARCHAR(255) DEFAULT 'NONE' NOT NULL,
   hosts TEXT,
   tasks TEXT,
-  item_text VARCHAR(1024),
+  item_text TEXT,
   CONSTRAINT PK_upgrade_item PRIMARY KEY (upgrade_item_id),
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );

http://git-wip-us.apache.org/repos/asf/ambari/blob/7a7d2320/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index aa06c4d..f54a232 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -858,7 +858,7 @@ CREATE TABLE upgrade_item (
   state VARCHAR(255) DEFAULT 'NONE' NOT NULL,
   hosts TEXT,
   tasks TEXT,
-  item_text VARCHAR(1024),
+  item_text TEXT,
   CONSTRAINT PK_upgrade_item PRIMARY KEY CLUSTERED (upgrade_item_id),
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );


[24/38] ambari git commit: Added swagger annotations to the new endpoint

Posted by lp...@apache.org.
Added swagger annotations to the new endpoint


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/db8874b6
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/db8874b6
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/db8874b6

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: db8874b6953e49b13baf3f1dd30d29c2a29949f9
Parents: 885761f
Author: Balázs Bence Sári <bs...@hortonworks.com>
Authored: Thu Jul 6 18:36:18 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:29 2017 +0200

----------------------------------------------------------------------
 .../AmbariConfigurationRequestSwagger.java      | 48 +++++++++++++++
 .../AmbariConfigurationResponseSwagger.java     | 40 +++++++++++++
 .../services/AmbariConfigurationService.java    | 62 +++++++++++++++++---
 3 files changed, 143 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/db8874b6/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
new file mode 100644
index 0000000..d6714f9
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
@@ -0,0 +1,48 @@
+/*
+ * 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.Map;
+
+import org.apache.ambari.server.controller.ApiModel;
+import org.apache.ambari.server.orm.entities.ConfigurationBaseEntity;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Request data model for {@link org.apache.ambari.server.api.services.AmbariConfigurationService}
+ */
+public interface AmbariConfigurationRequestSwagger extends ApiModel {
+
+  @ApiModelProperty(name = "AmbariConfiguration")
+  AmbariConfigurationRequestInfo getAmbariConfiguration();
+
+  interface AmbariConfigurationRequestInfo {
+    @ApiModelProperty
+    Long getId();
+
+    @ApiModelProperty
+    Map<String, Object> getData();
+
+    @ApiModelProperty
+    String getType();
+
+    @ApiModelProperty
+    Long getVersion();
+
+    @ApiModelProperty(name = "version_tag")
+    String getVersionTag();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/db8874b6/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java
new file mode 100644
index 0000000..c55ac1d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java
@@ -0,0 +1,40 @@
+/*
+ * 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.Map;
+
+import org.apache.ambari.server.controller.ApiModel;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Response data model for {@link org.apache.ambari.server.api.services.AmbariConfigurationService}
+ */
+public interface AmbariConfigurationResponseSwagger extends ApiModel {
+
+  @ApiModelProperty(name = "AmbariConfiguration")
+  AmbariConfigurationResponseInfo getAmbariConfigurationResponse();
+
+  interface AmbariConfigurationResponseInfo {
+    @ApiModelProperty
+    Long getId();
+
+    @ApiModelProperty
+    Map<String, Object> getData();
+
+    @ApiModelProperty
+    String getType();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/db8874b6/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
index 0fa6e44..0c159b9 100644
--- 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
@@ -70,9 +70,12 @@ import io.swagger.annotations.ApiResponses;
  * </pre>
  */
 @Path("/configurations/")
-@Api(value = "/configurations", description = "Endpoint for Ambari configuration related operations")
+@Api(value = "Ambari Configurations", description = "Endpoint for Ambari configuration related operations")
 public class AmbariConfigurationService extends BaseService {
 
+  private static final String AMBARI_CONFIGURATION_REQUEST_TYPE =
+      "org.apache.ambari.server.api.services.AmbariConfigurationRequestSwagger";
+
   /**
    * Creates an ambari configuration resource.
    *
@@ -83,9 +86,10 @@ public class AmbariConfigurationService extends BaseService {
    */
   @POST
   @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Creates an ambari configuration resource")
+  @ApiOperation(value = "Creates an ambari configuration resource",
+      nickname = "AmbariConfigurationService#createAmbariConfiguration")
   @ApiImplicitParams({
-    @ApiImplicitParam(dataType = "", paramType = PARAM_TYPE_BODY)
+      @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
   })
   @ApiResponses({
     @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION),
@@ -103,7 +107,26 @@ public class AmbariConfigurationService extends BaseService {
 
   @GET
   @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Retrieve ambari configuration resources")
+  @ApiOperation(value = "Retrieve all ambari configuration resources",
+      nickname = "AmbariConfigurationService#getAmbariConfigurations",
+      notes = "Returns all Ambari configurations.",
+      response = AmbariConfigurationResponseSwagger.class,
+      responseContainer = RESPONSE_CONTAINER_LIST)
+  @ApiImplicitParams({
+      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION,
+          defaultValue = "AmbariConfiguration/data, AmbariConfiguration/id, AmbariConfiguration/type",
+          dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION,
+          defaultValue = "AmbariConfiguration/id",
+          dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+  })
+  @ApiResponses(value = {
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
+  })
   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));
@@ -112,7 +135,18 @@ public class AmbariConfigurationService extends BaseService {
   @GET
   @Path("{configurationId}")
   @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Retrieve ambari configuration resource")
+  @ApiOperation(value = "Retrieve the details of an ambari configuration resource",
+      nickname = "AmbariConfigurationService#getAmbariConfiguration",
+      response = AmbariConfigurationResponseSwagger.class)
+  @ApiImplicitParams({
+      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "AmbariConfiguration/*",
+          dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+  })
+  @ApiResponses(value = {
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
+  })
   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,
@@ -121,7 +155,20 @@ public class AmbariConfigurationService extends BaseService {
 
   @PUT
   @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Update ambari configuration resources")
+  @ApiOperation(value = "Updates ambari configuration resources - Not implemented yet",
+    nickname = "AmbariConfigurationService#updateAmbariConfiguration")
+  @ApiImplicitParams({
+      @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_OK, 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_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 updateAmbariConfiguration() {
     throw new UnsupportedOperationException("Not yet implemented");
   }
@@ -129,7 +176,8 @@ public class AmbariConfigurationService extends BaseService {
   @DELETE
   @Path("{configurationId}")
   @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Deletes an ambari configuration resource")
+  @ApiOperation(value = "Deletes an ambari configuration resource",
+      nickname = "AmbariConfigurationService#deleteAmbariConfiguration")
   @ApiResponses({
     @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
     @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),


[09/38] ambari git commit: AMBARI-21929. UI task for Host Recovery. (Ishan via Jaimin)

Posted by lp...@apache.org.
AMBARI-21929. UI task for Host Recovery. (Ishan via Jaimin)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/bb4645f7
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/bb4645f7
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/bb4645f7

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: bb4645f7c0e8242a397b192cabd326bef0d99700
Parents: 9316ea8
Author: Jaimin Jetly <ja...@hortonworks.com>
Authored: Tue Sep 12 11:13:39 2017 -0700
Committer: Jaimin Jetly <ja...@hortonworks.com>
Committed: Tue Sep 12 11:13:39 2017 -0700

----------------------------------------------------------------------
 ambari-web/app/controllers/main/host/details.js | 143 +++++++++++++++++++
 ambari-web/app/messages.js                      |   8 ++
 ambari-web/app/templates/main/host/details.hbs  |   3 +
 .../main/host/details/recoverHostErrorPopup.hbs |  23 +++
 .../main/host/details/recoverHostPopup.hbs      |  22 +++
 5 files changed, 199 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/bb4645f7/ambari-web/app/controllers/main/host/details.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/details.js b/ambari-web/app/controllers/main/host/details.js
index cf223d7..ad2ac98 100644
--- a/ambari-web/app/controllers/main/host/details.js
+++ b/ambari-web/app/controllers/main/host/details.js
@@ -3101,5 +3101,148 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow
     } else {
       this.set('isConfigsLoadingInProgress', false);
     }
+  },
+  
+  recoverHost: function() {
+    var components = this.get('content.hostComponents');
+    var hostName = this.get('content.publicHostName');
+    var self = this;
+    var batches = [
+      {
+        "order_id": 1,
+        "type": "PUT",
+        "uri": App.get('apiPrefix') + "/clusters/" + App.get('clusterName') + "/hosts/" + hostName + "/host_components",
+        "RequestBodyInfo": {
+          "RequestInfo": {
+            context: Em.I18n.t('hosts.host.recover.initAllComponents.context'),
+            operation_level: {
+              level: "HOST",
+              cluster_name: App.get('clusterName'),
+              host_name: hostName
+            },
+            query: "HostRoles/component_name.in(" + components.mapProperty('componentName').join(',') + ")"
+          },
+          "Body": {
+            HostRoles: {
+              state: "INIT"
+            }
+          }
+        }
+    }];
+    batches.push(
+      {
+        "order_id": 2,
+        "type": "PUT",
+        "uri": App.get('apiPrefix') + "/clusters/" + App.get('clusterName') + "/hosts/" + hostName + "/host_components",
+        "RequestBodyInfo": {
+          "RequestInfo": {
+            context: Em.I18n.t('hosts.host.recover.installAllComponents.context'),
+            operation_level: {
+              level: "HOST",
+              cluster_name: App.get('clusterName'),
+              host_name: hostName
+            },
+            query: "HostRoles/component_name.in(" + components.mapProperty('componentName').join(',') + ")"
+          },
+          "Body": {
+            HostRoles: {
+              state: "INSTALLED"
+            }
+          }
+        }
+    });
+
+    if(App.get('isKerberosEnabled')) {
+      batches.push({
+        "order_id": 3,
+        "type": "PUT",
+        "uri": App.get('apiPrefix') + "/clusters/" + App.get('clusterName'),
+        "RequestBodyInfo": {
+          "RequestInfo": {
+            context: Em.I18n.t('hosts.host.recover.regenerateKeytabs.context'),
+            query: "regenerate_keytabs=all&regenerate_hosts=" + hostName + "&ignore_config_updates=true",
+          },
+          "Body": {
+            Clusters: {
+             security_type: "KERBEROS"
+            }
+          }
+        }
+      });
+    }
+    App.get('router.mainAdminKerberosController').getSecurityType(function () {
+      App.get('router.mainAdminKerberosController').getKDCSessionState(function () {
+        self._doRecoverHost(batches);
+      });
+    });
+  },
+
+  _doRecoverHost: function (batches) {
+    App.ajax.send ({
+      name: 'common.batch.request_schedules',
+      sender: this,
+      data: {
+        intervalTimeSeconds: 1,
+        tolerateSize: 0,
+        batches: batches
+      },
+      success:'recoverHostSuccessCallback',
+      showLoadingPopup: true
+    });
+  },
+
+  recoverHostSuccessCallback: function (data) {
+    if (data && (data.Requests || data.resources[0].RequestSchedule)) {
+      this.showBackgroundOperationsPopup();
+      return true;
+    } else {
+      return false;
+    }
+  },
+
+  recoverHostDisabled: function() {
+
+    var isDisabled = false;
+    var allowedStates = [App.HostComponentStatus.stopped, App.HostComponentStatus.install_failed, App.HostComponentStatus.init];
+    this.get('content.hostComponents').forEach(function (component) {
+      isDisabled = isDisabled ? true : !allowedStates.contains(component.get('workStatus'));
+    });
+    return isDisabled;
+  }.property('content.hostComponents.@each.workStatus'),
+
+  confirmRecoverHost: function() {
+    var self = this;
+    var componentsNotStopped = [];
+    var allowedStates = [App.HostComponentStatus.stopped, App.HostComponentStatus.install_failed, App.HostComponentStatus.init];
+    this.get('content.hostComponents').forEach(function (component) {
+      if(!allowedStates.contains(component.get('workStatus'))) {
+        componentsNotStopped.push(component.get('componentName'));
+      }
+    });
+    if(componentsNotStopped.length) {
+      App.ModalPopup.show({
+        header: Em.I18n.t('hosts.recover.error.popup.title'),
+        recoverErrorPopupBody: Em.I18n.t('hosts.recover.error.popup.body').format(componentsNotStopped.toString()),
+        componentsStr: componentsNotStopped.toString(),
+        bodyClass: Em.View.extend({
+          templateName: require('templates/main/host/details/recoverHostErrorPopup')
+        }),
+        secondary: false
+      });
+    } else {
+      App.ModalPopup.show({
+        header: Em.I18n.t('hosts.recover.popup.title'),
+        bodyClass: Em.View.extend({
+          templateName: require('templates/main/host/details/recoverHostPopup')
+        }),
+        primary: Em.I18n.t('yes'),
+        secondary: Em.I18n.t('no'),
+        onPrimary: function () {
+          self.recoverHost();
+          this.hide();
+        }
+      });
+    }
   }
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb4645f7/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index bda8228..869608a 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -2697,6 +2697,7 @@ Em.I18n.translations = {
   'hosts.host.details.refreshConfigs':'Refresh configs',
   'hosts.host.details.for.postfix':'{0} for host',
   'hosts.host.details.setRackId':'Set Rack',
+  'hosts.host.details.recoverHost': 'Recover Host',
   'host.host.details.installClients': 'Install clients',
   'host.host.details.reinstallClients': 'Reinstall clients',
   'host.host.details.checkHost': 'Check host',
@@ -2762,6 +2763,9 @@ Em.I18n.translations = {
   'hosts.host.maintainance.stopAllComponents.context': 'Stop All Host Components',
   'hosts.host.maintainance.startAllComponents.context': 'Start All Host Components',
   'hosts.host.maintainance.reinstallFailedComponents.context': 'Reinstall Failed Components',
+  'hosts.host.recover.initAllComponents.context': 'Init All Host Components',
+  'hosts.host.recover.installAllComponents.context': 'Install All Host Components',
+  'hosts.host.recover.regenerateKeytabs.context': 'Regenerate keytabs',
   'hosts.host.alerts.st':'&nbsp;!&nbsp;',
   'hosts.decommission.popup.body':'Are you sure?',
   'hosts.decommission.popup.header':'Confirmation',
@@ -2777,6 +2781,10 @@ Em.I18n.translations = {
   'hosts.delete.popup.header':'Confirmation',
   'hosts.delete.popup.title':'Delete Host',
   'hosts.delete.popup.unknownComponents':'The following components have unknown status:',
+  'hosts.recover.popup.title': 'Confirmation',
+  'hosts.recover.popup.body': 'This action will completely re-install all components on this host, and should only be used when restoring a host using replacement hardware. <strong>Are you sure you want to continue?<strong>',
+  'hosts.recover.error.popup.title': 'Cannot Recover Host',
+  'hosts.recover.error.popup.body': 'Host cannot be recovered unless every host component is not in Stopped, Install Failed or Init state',
   'hosts.cant.do.popup.title':'Unable to Delete Host',
   'hosts.cant.do.popup.masterList.body':'This host cannot be deleted since it has the following master components:',
   'hosts.cant.do.popup.masterList.body.end':'To delete this host, you must first move all the master components listed above.',

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb4645f7/ambari-web/app/templates/main/host/details.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host/details.hbs b/ambari-web/app/templates/main/host/details.hbs
index bd75f5c..15b0f4a 100644
--- a/ambari-web/app/templates/main/host/details.hbs
+++ b/ambari-web/app/templates/main/host/details.hbs
@@ -65,6 +65,9 @@
                   </div>
                 </li>
               {{/if}}
+              <li>
+                <a {{action "confirmRecoverHost" target="controller"}}><i class="icon-time"></i> {{t hosts.host.details.recoverHost}} </a>
+              </li>
             </ul>
           </div>
         </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb4645f7/ambari-web/app/templates/main/host/details/recoverHostErrorPopup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host/details/recoverHostErrorPopup.hbs b/ambari-web/app/templates/main/host/details/recoverHostErrorPopup.hbs
new file mode 100644
index 0000000..1152801
--- /dev/null
+++ b/ambari-web/app/templates/main/host/details/recoverHostErrorPopup.hbs
@@ -0,0 +1,23 @@
+{{!
+* 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.
+}}
+
+<div class="dialog-delete-component">
+  <div class="warning">
+    <i class="icon-warning-sign"></i> {{recoverErrorPopupBody}}
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb4645f7/ambari-web/app/templates/main/host/details/recoverHostPopup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host/details/recoverHostPopup.hbs b/ambari-web/app/templates/main/host/details/recoverHostPopup.hbs
new file mode 100644
index 0000000..2534bc6
--- /dev/null
+++ b/ambari-web/app/templates/main/host/details/recoverHostPopup.hbs
@@ -0,0 +1,22 @@
+{{!
+* 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.
+}}
+
+
+<div class="alert">
+  {{t hosts.recover.popup.body}}
+</div>


[22/38] ambari git commit: AMBARI-21943. LLAP: Daemon is hung when task is killed in the middle of orc tail reads (org.apache.hadoop.hdfs.shortcircuit.DfsClientShmManager.allocSlot).

Posted by lp...@apache.org.
AMBARI-21943. LLAP: Daemon is hung when task is killed in the middle of orc tail reads (org.apache.hadoop.hdfs.shortcircuit.DfsClientShmManager.allocSlot).


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/df3a66d9
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/df3a66d9
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/df3a66d9

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: df3a66d9767646f6a38b3c64a587a4ab647bf868
Parents: 6c40fdf
Author: Swapan Shridhar <ss...@hortonworks.com>
Authored: Tue Sep 12 16:52:11 2017 -0700
Committer: Swapan Shridhar <ss...@hortonworks.com>
Committed: Wed Sep 13 15:52:49 2017 -0700

----------------------------------------------------------------------
 .../stacks/HDP/2.5/upgrades/config-upgrade.xml        |  6 ++++++
 .../HDP/2.5/upgrades/nonrolling-upgrade-2.6.xml       |  5 +++++
 .../resources/stacks/HDP/2.5/upgrades/upgrade-2.6.xml |  1 +
 .../HIVE/configuration/hive-interactive-site.xml      | 14 ++++++++++++++
 4 files changed, 26 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/df3a66d9/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/config-upgrade.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/config-upgrade.xml b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/config-upgrade.xml
index 13173d2..f5fa744 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/config-upgrade.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/config-upgrade.xml
@@ -532,6 +532,12 @@
             <set key="tez.runtime.shuffle.parallel.copies" value="8"/>
           </definition>
 
+          <definition xsi:type="configure" id="hdp_2_6_maint_llap_config" summary="Updating LLAP configuration">
+            <type>hive-interactive-site</type>
+            <set key="dfs.short.circuit.shared.memory.watcher.interrupt.check.ms" value="0" />
+            <set key="dfs.client.mmap.enabled" value="false" />
+          </definition>
+
         </changes>
 
       </component>

http://git-wip-us.apache.org/repos/asf/ambari/blob/df3a66d9/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.6.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.6.xml b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.6.xml
index 90a7d97..c509f34 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.6.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.6.xml
@@ -635,6 +635,11 @@
           <summary>Updating hive atlas application properties</summary>
         </task>
       </execute-stage>
+
+      <execute-stage service="HIVE" component="HIVE_SERVER_INTERACTIVE" title="Updating DFS related LLAP configurations">
+        <task xsi:type="configure" id="hdp_2_6_maint_llap_config"/>
+      </execute-stage>
+
       <!-- SPARK -->
       <execute-stage service="SPARK" component="LIVY_SERVER" title="Apply config changes for Livy Server">
         <task xsi:type="configure" id="hdp_2_5_0_0_rename_spark_livy_configs"/>

http://git-wip-us.apache.org/repos/asf/ambari/blob/df3a66d9/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.6.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.6.xml b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.6.xml
index 5ee82c3..5f1bf12 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.6.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.6.xml
@@ -860,6 +860,7 @@
           <task xsi:type="configure" id="llap_update_shuffle_parallel_copies"/>
           <task xsi:type="configure" id="llap_update_settings"/>
           <task xsi:type="configure" id="llap_update_tez_settings"/>
+          <task xsi:type="configure" id="hdp_2_6_maint_llap_config"/>
         </pre-upgrade>
         
         <pre-downgrade />

http://git-wip-us.apache.org/repos/asf/ambari/blob/df3a66d9/ambari-server/src/main/resources/stacks/HDP/2.6/services/HIVE/configuration/hive-interactive-site.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.6/services/HIVE/configuration/hive-interactive-site.xml b/ambari-server/src/main/resources/stacks/HDP/2.6/services/HIVE/configuration/hive-interactive-site.xml
index cb4f947..aae2efa 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.6/services/HIVE/configuration/hive-interactive-site.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.6/services/HIVE/configuration/hive-interactive-site.xml
@@ -110,4 +110,18 @@ limitations under the License.
     <on-ambari-upgrade add="false"/>
   </property>
 
+  <property>
+    <name>dfs.client.mmap.enabled</name>
+    <value>false</value>
+    <description>Disable HDFS caching fo LLAP</description>
+    <on-ambari-upgrade add="false"/>
+  </property>
+
+  <property>
+    <name>dfs.short.circuit.shared.memory.watcher.interrupt.check.ms</name>
+    <value>0</value>
+    <description>Disable HDFS caching fo LLAP</description>
+    <on-ambari-upgrade add="false"/>
+  </property>
+
 </configuration>


[11/38] ambari git commit: AMBARI-21939 : Ambari HDFS Heatmaps are not showing data (Not Applicable) for bytes read, bytes written & DataNode Process Network I/O Utilization. (avijayan)

Posted by lp...@apache.org.
AMBARI-21939 : Ambari HDFS Heatmaps are not showing data (Not Applicable) for bytes read, bytes written & DataNode Process Network I/O Utilization. (avijayan)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/a49121b9
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/a49121b9
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/a49121b9

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: a49121b9af276f45ef26e0b320de48d6ef6e7563
Parents: 7fa7a6c
Author: Aravindan Vijayan <av...@hortonworks.com>
Authored: Tue Sep 12 17:07:14 2017 -0700
Committer: Aravindan Vijayan <av...@hortonworks.com>
Committed: Tue Sep 12 17:07:14 2017 -0700

----------------------------------------------------------------------
 .../server/upgrade/UpgradeCatalog260.java       | 16 ++++
 .../PERF/1.0/services/FAKEHDFS/widgets.json     | 48 +++++------
 .../server/upgrade/UpgradeCatalog260Test.java   | 87 ++++++++++++++++++++
 3 files changed, 127 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/a49121b9/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
index 2de85fc..b17569e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
@@ -21,6 +21,7 @@ import static org.apache.ambari.server.view.ViewContextImpl.CORE_SITE;
 
 import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -401,6 +402,7 @@ public class UpgradeCatalog260 extends AbstractUpgradeCatalog {
     ensureZeppelinProxyUserConfigs();
     updateKerberosDescriptorArtifacts();
     updateAmsConfigs();
+    updateHDFSWidgetDefinition();
   }
 
   public int getCurrentVersionID() throws AmbariException, SQLException {
@@ -565,4 +567,18 @@ public class UpgradeCatalog260 extends AbstractUpgradeCatalog {
       }
     }
   }
+
+  protected void updateHDFSWidgetDefinition() throws AmbariException {
+    LOG.info("Updating HDFS widget definition.");
+
+    Map<String, List<String>> widgetMap = new HashMap<>();
+    Map<String, String> sectionLayoutMap = new HashMap<>();
+
+    List<String> hdfsHeatmapWidgets = new ArrayList<>(Arrays.asList("HDFS Bytes Read", "HDFS Bytes Written",
+      "DataNode Process Disk I/O Utilization", "DataNode Process Network I/O Utilization"));
+    widgetMap.put("HDFS_HEATMAPS", hdfsHeatmapWidgets);
+    sectionLayoutMap.put("HDFS_HEATMAPS", "default_hdfs_heatmap");
+
+    updateWidgetDefinitionsForService("HDFS", widgetMap, sectionLayoutMap);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a49121b9/ambari-server/src/main/resources/stacks/PERF/1.0/services/FAKEHDFS/widgets.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/PERF/1.0/services/FAKEHDFS/widgets.json b/ambari-server/src/main/resources/stacks/PERF/1.0/services/FAKEHDFS/widgets.json
index 7a793f8..205a364 100644
--- a/ambari-server/src/main/resources/stacks/PERF/1.0/services/FAKEHDFS/widgets.json
+++ b/ambari-server/src/main/resources/stacks/PERF/1.0/services/FAKEHDFS/widgets.json
@@ -416,8 +416,8 @@
           "is_visible": true,
           "metrics": [
             {
-              "name": "dfs.datanode.BytesRead._rate",
-              "metric_path": "metrics/dfs/datanode/bytes_read._rate",
+              "name": "dfs.datanode.BytesRead",
+              "metric_path": "metrics/dfs/datanode/bytes_read",
               "service_name": "FAKEHDFS",
               "component_name": "FAKEDATANODE"
             }
@@ -425,7 +425,7 @@
           "values": [
             {
               "name": "FAKEHDFS Bytes Read",
-              "value": "${dfs.datanode.BytesRead._rate}"
+              "value": "${dfs.datanode.BytesRead}"
             }
           ],
           "properties": {
@@ -440,8 +440,8 @@
           "is_visible": false,
           "metrics": [
             {
-              "name": "dfs.datanode.BytesWritten._rate",
-              "metric_path": "metrics/dfs/datanode/bytes_written._rate",
+              "name": "dfs.datanode.BytesWritten",
+              "metric_path": "metrics/dfs/datanode/bytes_written",
               "service_name": "FAKEHDFS",
               "component_name": "FAKEDATANODE"
             }
@@ -449,7 +449,7 @@
           "values": [
             {
               "name": "FAKEHDFS Bytes Written",
-              "value": "${dfs.datanode.BytesWritten._rate}"
+              "value": "${dfs.datanode.BytesWritten}"
             }
           ],
           "properties": {
@@ -537,26 +537,26 @@
           "is_visible": false,
           "metrics": [
             {
-              "name": "dfs.datanode.BytesRead._rate",
-              "metric_path": "metrics/dfs/datanode/bytes_read._rate",
+              "name": "dfs.datanode.BytesRead",
+              "metric_path": "metrics/dfs/datanode/bytes_read",
               "service_name": "FAKEHDFS",
               "component_name": "FAKEDATANODE"
             },
             {
-              "name": "dfs.datanode.BytesWritten._rate",
-              "metric_path": "metrics/dfs/datanode/bytes_written._rate",
+              "name": "dfs.datanode.BytesWritten",
+              "metric_path": "metrics/dfs/datanode/bytes_written",
               "service_name": "FAKEHDFS",
               "component_name": "FAKEDATANODE"
             },
             {
-              "name": "dfs.datanode.TotalReadTime._rate",
-              "metric_path": "metrics/dfs/datanode/TotalReadTime._rate",
+              "name": "dfs.datanode.TotalReadTime",
+              "metric_path": "metrics/dfs/datanode/TotalReadTime",
               "service_name": "FAKEHDFS",
               "component_name": "FAKEDATANODE"
             },
             {
-              "name": "dfs.datanode.TotalWriteTime._rate",
-              "metric_path": "metrics/dfs/datanode/TotalWriteTime._rate",
+              "name": "dfs.datanode.TotalWriteTime",
+              "metric_path": "metrics/dfs/datanode/TotalWriteTime",
               "service_name": "FAKEHDFS",
               "component_name": "FAKEDATANODE"
             }
@@ -564,7 +564,7 @@
           "values": [
             {
               "name": "FAKEDataNode Process Disk I/O Utilization",
-              "value": "${((dfs.datanode.BytesRead._rate/dfs.datanode.TotalReadTime._rate)+(dfs.datanode.BytesWritten._rate/dfs.datanode.TotalWriteTime._rate))*50}"
+              "value": "${((dfs.datanode.BytesRead/dfs.datanode.TotalReadTime)+(dfs.datanode.BytesWritten/dfs.datanode.TotalWriteTime))*50}"
             }
           ],
           "properties": {
@@ -579,26 +579,26 @@
           "is_visible": false,
           "metrics": [
             {
-              "name": "dfs.datanode.RemoteBytesRead._rate",
-              "metric_path": "metrics/dfs/datanode/RemoteBytesRead._rate",
+              "name": "dfs.datanode.RemoteBytesRead",
+              "metric_path": "metrics/dfs/datanode/RemoteBytesRead",
               "service_name": "FAKEHDFS",
               "component_name": "FAKEDATANODE"
             },
             {
-              "name": "dfs.datanode.ReadsFromRemoteClient._rate",
-              "metric_path": "metrics/dfs/datanode/reads_from_remote_client._rate",
+              "name": "dfs.datanode.ReadsFromRemoteClient",
+              "metric_path": "metrics/dfs/datanode/reads_from_remote_client",
               "service_name": "FAKEHDFS",
               "component_name": "FAKEDATANODE"
             },
             {
-              "name": "dfs.datanode.RemoteBytesWritten._rate",
-              "metric_path": "metrics/dfs/datanode/RemoteBytesWritten._rate",
+              "name": "dfs.datanode.RemoteBytesWritten",
+              "metric_path": "metrics/dfs/datanode/RemoteBytesWritten",
               "service_name": "FAKEHDFS",
               "component_name": "FAKEDATANODE"
             },
             {
-              "name": "dfs.datanode.WritesFromRemoteClient._rate",
-              "metric_path": "metrics/dfs/datanode/writes_from_remote_client._rate",
+              "name": "dfs.datanode.WritesFromRemoteClient",
+              "metric_path": "metrics/dfs/datanode/writes_from_remote_client",
               "service_name": "FAKEHDFS",
               "component_name": "FAKEDATANODE"
             }
@@ -606,7 +606,7 @@
           "values": [
             {
               "name": "FAKEDataNode Process Network I/O Utilization",
-              "value": "${((dfs.datanode.RemoteBytesRead._rate/dfs.datanode.ReadsFromRemoteClient._rate)+(dfs.datanode.RemoteBytesWritten._rate/dfs.datanode.WritesFromRemoteClient._rate))*50}"
+              "value": "${((dfs.datanode.RemoteBytesRead/dfs.datanode.ReadsFromRemoteClient)+(dfs.datanode.RemoteBytesWritten/dfs.datanode.WritesFromRemoteClient))*50}"
             }
           ],
           "properties": {

http://git-wip-us.apache.org/repos/asf/ambari/blob/a49121b9/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
index b70f37b..d9c7957 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
@@ -50,8 +50,10 @@ import java.util.Set;
 import javax.persistence.EntityManager;
 
 import com.google.common.collect.Maps;
+import com.google.inject.AbstractModule;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.ActionManager;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.AmbariManagementControllerImpl;
@@ -60,17 +62,23 @@ import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.orm.DBAccessor.DBColumnInfo;
 import org.apache.ambari.server.orm.dao.ArtifactDAO;
+import org.apache.ambari.server.orm.dao.WidgetDAO;
 import org.apache.ambari.server.orm.entities.ArtifactEntity;
+import org.apache.ambari.server.orm.entities.WidgetEntity;
+import org.apache.ambari.server.stack.StackManagerFactory;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.StackInfo;
 import org.apache.ambari.server.state.kerberos.KerberosComponentDescriptor;
 import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
 import org.apache.ambari.server.state.kerberos.KerberosDescriptorFactory;
 import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
 import org.apache.ambari.server.state.stack.OsFamily;
+import org.apache.commons.io.FileUtils;
 import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.easymock.EasyMockRunner;
@@ -80,7 +88,9 @@ import org.easymock.MockType;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 
 import com.google.gson.Gson;
@@ -142,6 +152,9 @@ public class UpgradeCatalog260Test {
   @Mock(type = MockType.NICE)
   private Injector injector;
 
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
   @Before
   public void init() {
     reset(entityManagerProvider, injector);
@@ -737,4 +750,78 @@ public class UpgradeCatalog260Test {
     assertTrue(Maps.difference(newProperties, updatedProperties).areEqual());
   }
 
+  @Test
+   public void testHDFSWidgetUpdate() throws Exception {
+         final Clusters clusters = createNiceMock(Clusters.class);
+         final Cluster cluster = createNiceMock(Cluster.class);
+         final AmbariManagementController controller = createNiceMock(AmbariManagementController.class);
+         final Gson gson = new Gson();
+         final WidgetDAO widgetDAO = createNiceMock(WidgetDAO.class);
+         final AmbariMetaInfo metaInfo = createNiceMock(AmbariMetaInfo.class);
+         WidgetEntity widgetEntity = createNiceMock(WidgetEntity.class);
+         StackId stackId = new StackId("HDP", "2.0.0");
+         StackInfo stackInfo = createNiceMock(StackInfo.class);
+         ServiceInfo serviceInfo = createNiceMock(ServiceInfo.class);
+         Service service  = createNiceMock(Service.class);
+
+           String widgetStr = "{\n" +
+             "  \"layouts\": [\n" +
+             "      {\n" +
+             "      \"layout_name\": \"default_hdfs_heatmap\",\n" +
+             "      \"display_name\": \"Standard HDFS HeatMaps\",\n" +
+             "      \"section_name\": \"HDFS_HEATMAPS\",\n" +
+             "      \"widgetLayoutInfo\": [\n" +
+             "        {\n" +
+             "          \"widget_name\": \"HDFS Bytes Read\",\n" +
+             "          \"metrics\": [],\n" +
+             "          \"values\": []\n" +
+             "        }\n" +
+             "      ]\n" +
+             "    }\n" +
+             "  ]\n" +
+             "}";
+
+           File dataDirectory = temporaryFolder.newFolder();
+         File file = new File(dataDirectory, "hdfs_widget.json");
+         FileUtils.writeStringToFile(file, widgetStr);
+
+           final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+       @Override
+       protected void configure() {
+                 bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
+                 bind(AmbariManagementController.class).toInstance(controller);
+                 bind(Clusters.class).toInstance(clusters);
+                 bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
+                 bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class));
+                 bind(Gson.class).toInstance(gson);
+                 bind(WidgetDAO.class).toInstance(widgetDAO);
+                 bind(StackManagerFactory.class).toInstance(createNiceMock(StackManagerFactory.class));
+                 bind(AmbariMetaInfo.class).toInstance(metaInfo);
+               }
+     });
+         expect(controller.getClusters()).andReturn(clusters).anyTimes();
+         expect(clusters.getClusters()).andReturn(new HashMap<String, Cluster>() {{
+             put("normal", cluster);
+           }}).anyTimes();
+         expect(cluster.getServices()).andReturn(Collections.singletonMap("HDFS", service)).anyTimes();
+         expect(cluster.getClusterId()).andReturn(1L).anyTimes();
+         expect(service.getDesiredStackId()).andReturn(stackId).anyTimes();
+         expect(stackInfo.getService("HDFS")).andReturn(serviceInfo);
+         expect(cluster.getDesiredStackVersion()).andReturn(stackId).anyTimes();
+         expect(metaInfo.getStack("HDP", "2.0.0")).andReturn(stackInfo).anyTimes();
+         expect(serviceInfo.getWidgetsDescriptorFile()).andReturn(file).anyTimes();
+
+           expect(widgetDAO.findByName(1L, "HDFS Bytes Read", "ambari", "HDFS_HEATMAPS"))
+             .andReturn(Collections.singletonList(widgetEntity));
+         expect(widgetDAO.merge(widgetEntity)).andReturn(null);
+         expect(widgetEntity.getWidgetName()).andReturn("HDFS Bytes Read").anyTimes();
+
+           replay(clusters, cluster, controller, widgetDAO, metaInfo, widgetEntity, stackInfo, serviceInfo, service);
+
+           mockInjector.getInstance(UpgradeCatalog260.class).updateHDFSWidgetDefinition();
+
+           verify(clusters, cluster, controller, widgetDAO, widgetEntity, stackInfo, serviceInfo);
+       }
+
+
 }


[26/38] ambari git commit: AMBARI-21307 Implemented PUT operation, added unit tests

Posted by lp...@apache.org.
AMBARI-21307 Implemented PUT operation, added unit tests


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/642b5780
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/642b5780
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/642b5780

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 642b5780e0d99f696ce6ab1028fbb3c0125f3429
Parents: db8874b
Author: lpuskas <lp...@apache.org>
Authored: Thu Jul 13 16:20:58 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:29 2017 +0200

----------------------------------------------------------------------
 .../services/AmbariConfigurationService.java    |  89 ++++---
 .../server/controller/ControllerModule.java     |   2 +
 .../controller/ResourceProviderFactory.java     |  23 +-
 .../AbstractControllerResourceProvider.java     |   2 +
 .../AmbariConfigurationResourceProvider.java    |  88 +++++--
 .../internal/DefaultProviderModule.java         |   2 -
 .../server/orm/dao/AmbariConfigurationDAO.java  |   4 +
 ...AmbariConfigurationResourceProviderTest.java | 231 +++++++++++++++++++
 8 files changed, 363 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/642b5780/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
index 0c159b9..0632361 100644
--- 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
@@ -56,16 +56,10 @@ import io.swagger.annotations.ApiResponses;
  *            "data": [
  *                {
  *                 "authentication.ldap.primaryUrl": "localhost:33389"
- *                },
- *                {
- *                "authentication.ldap.secondaryUrl": "localhost:333"
- *                 },
- *                 {
+                   "authentication.ldap.secondaryUrl": "localhost:333"
  *                 "authentication.ldap.baseDn": "dc=ambari,dc=apache,dc=org"
- *                 }
- *                 // ......
- *             ]
- *         }
+  *                 // ......
+ *         ]
  *     }
  * </pre>
  */
@@ -74,7 +68,7 @@ import io.swagger.annotations.ApiResponses;
 public class AmbariConfigurationService extends BaseService {
 
   private static final String AMBARI_CONFIGURATION_REQUEST_TYPE =
-      "org.apache.ambari.server.api.services.AmbariConfigurationRequestSwagger";
+    "org.apache.ambari.server.api.services.AmbariConfigurationRequestSwagger";
 
   /**
    * Creates an ambari configuration resource.
@@ -87,9 +81,9 @@ public class AmbariConfigurationService extends BaseService {
   @POST
   @Produces(MediaType.TEXT_PLAIN)
   @ApiOperation(value = "Creates an ambari configuration resource",
-      nickname = "AmbariConfigurationService#createAmbariConfiguration")
+    nickname = "AmbariConfigurationService#createAmbariConfiguration")
   @ApiImplicitParams({
-      @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
+    @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
   })
   @ApiResponses({
     @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION),
@@ -108,24 +102,24 @@ public class AmbariConfigurationService extends BaseService {
   @GET
   @Produces(MediaType.TEXT_PLAIN)
   @ApiOperation(value = "Retrieve all ambari configuration resources",
-      nickname = "AmbariConfigurationService#getAmbariConfigurations",
-      notes = "Returns all Ambari configurations.",
-      response = AmbariConfigurationResponseSwagger.class,
-      responseContainer = RESPONSE_CONTAINER_LIST)
+    nickname = "AmbariConfigurationService#getAmbariConfigurations",
+    notes = "Returns all Ambari configurations.",
+    response = AmbariConfigurationResponseSwagger.class,
+    responseContainer = RESPONSE_CONTAINER_LIST)
   @ApiImplicitParams({
-      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION,
-          defaultValue = "AmbariConfiguration/data, AmbariConfiguration/id, AmbariConfiguration/type",
-          dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
-      @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION,
-          defaultValue = "AmbariConfiguration/id",
-          dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
-      @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
-      @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
-      @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION,
+      defaultValue = "AmbariConfiguration/data, AmbariConfiguration/id, AmbariConfiguration/type",
+      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+    @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION,
+      defaultValue = "AmbariConfiguration/id",
+      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+    @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+    @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+    @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
   })
   @ApiResponses(value = {
-      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
-      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
+    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
   })
   public Response getAmbariConfigurations(String body, @Context HttpHeaders headers, @Context UriInfo uri) {
     return handleRequest(headers, body, uri, Request.Type.GET, createResource(Resource.Type.AmbariConfiguration,
@@ -136,16 +130,16 @@ public class AmbariConfigurationService extends BaseService {
   @Path("{configurationId}")
   @Produces(MediaType.TEXT_PLAIN)
   @ApiOperation(value = "Retrieve the details of an ambari configuration resource",
-      nickname = "AmbariConfigurationService#getAmbariConfiguration",
-      response = AmbariConfigurationResponseSwagger.class)
+    nickname = "AmbariConfigurationService#getAmbariConfiguration",
+    response = AmbariConfigurationResponseSwagger.class)
   @ApiImplicitParams({
-      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "AmbariConfiguration/*",
-          dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "AmbariConfiguration/*",
+      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
   })
   @ApiResponses(value = {
-      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
-      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
-      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
+    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+    @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
   })
   public Response getAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
                                          @PathParam("configurationId") String configurationId) {
@@ -154,30 +148,35 @@ public class AmbariConfigurationService extends BaseService {
   }
 
   @PUT
+  @Path("{configurationId}")
   @Produces(MediaType.TEXT_PLAIN)
   @ApiOperation(value = "Updates ambari configuration resources - Not implemented yet",
     nickname = "AmbariConfigurationService#updateAmbariConfiguration")
   @ApiImplicitParams({
-      @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
+    @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY),
+    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "AmbariConfiguration/*",
+      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
   })
   @ApiResponses({
-      @ApiResponse(code = HttpStatus.SC_OK, 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_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),
+    @ApiResponse(code = HttpStatus.SC_OK, 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_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 updateAmbariConfiguration() {
-    throw new UnsupportedOperationException("Not yet implemented");
+  public Response updateAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
+                                            @PathParam("configurationId") String configurationId) {
+    return handleRequest(headers, body, uri, Request.Type.PUT, createResource(Resource.Type.AmbariConfiguration,
+      Collections.singletonMap(Resource.Type.AmbariConfiguration, configurationId)));
   }
 
   @DELETE
   @Path("{configurationId}")
   @Produces(MediaType.TEXT_PLAIN)
   @ApiOperation(value = "Deletes an ambari configuration resource",
-      nickname = "AmbariConfigurationService#deleteAmbariConfiguration")
+    nickname = "AmbariConfigurationService#deleteAmbariConfiguration")
   @ApiResponses({
     @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
     @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),

http://git-wip-us.apache.org/repos/asf/ambari/blob/642b5780/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index e151e63..edabcdb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -62,6 +62,7 @@ import org.apache.ambari.server.cleanup.ClasspathScannerUtils;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.configuration.Configuration.ConnectionPoolType;
 import org.apache.ambari.server.configuration.Configuration.DatabaseType;
+import org.apache.ambari.server.controller.internal.AmbariConfigurationResourceProvider;
 import org.apache.ambari.server.controller.internal.ComponentResourceProvider;
 import org.apache.ambari.server.controller.internal.CredentialResourceProvider;
 import org.apache.ambari.server.controller.internal.HostComponentResourceProvider;
@@ -467,6 +468,7 @@ public class ControllerModule extends AbstractModule {
         .implement(ResourceProvider.class, Names.named("credential"), CredentialResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("kerberosDescriptor"), KerberosDescriptorResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("upgrade"), UpgradeResourceProvider.class)
+        .implement(ResourceProvider.class, Names.named("ambariConfiguration"), AmbariConfigurationResourceProvider.class)
         .build(ResourceProviderFactory.class));
 
     install(new FactoryModuleBuilder().implement(

http://git-wip-us.apache.org/repos/asf/ambari/blob/642b5780/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
index 3912138..36dfdf9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
@@ -22,23 +22,22 @@ package org.apache.ambari.server.controller;
 import java.util.Map;
 import java.util.Set;
 
+import javax.inject.Named;
+
 import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.Resource.Type;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 
-import com.google.inject.name.Named;
 
 public interface ResourceProviderFactory {
   @Named("host")
-  ResourceProvider getHostResourceProvider(Set<String> propertyIds,
-      Map<Type, String> keyPropertyIds,
-      AmbariManagementController managementController);
+  ResourceProvider getHostResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
+                                           AmbariManagementController managementController);
 
   @Named("hostComponent")
-  ResourceProvider getHostComponentResourceProvider(Set<String> propertyIds,
-      Map<Type, String> keyPropertyIds,
-      AmbariManagementController managementController);
+  ResourceProvider getHostComponentResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
+                                                    AmbariManagementController managementController);
 
   @Named("service")
   ResourceProvider getServiceResourceProvider(AmbariManagementController managementController);
@@ -47,9 +46,8 @@ public interface ResourceProviderFactory {
   ResourceProvider getComponentResourceProvider(AmbariManagementController managementController);
 
   @Named("member")
-  ResourceProvider getMemberResourceProvider(Set<String> propertyIds,
-      Map<Type, String> keyPropertyIds,
-      AmbariManagementController managementController);
+  ResourceProvider getMemberResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
+                                             AmbariManagementController managementController);
 
   @Named("hostKerberosIdentity")
   ResourceProvider getHostKerberosIdentityResourceProvider(AmbariManagementController managementController);
@@ -61,11 +59,12 @@ public interface ResourceProviderFactory {
   ResourceProvider getRepositoryVersionResourceProvider();
 
   @Named("kerberosDescriptor")
-  ResourceProvider getKerberosDescriptorResourceProvider(AmbariManagementController managementController,
-                                                         Set<String> propertyIds,
+  ResourceProvider getKerberosDescriptorResourceProvider(AmbariManagementController managementController, Set<String> propertyIds,
                                                          Map<Resource.Type, String> keyPropertyIds);
 
   @Named("upgrade")
   UpgradeResourceProvider getUpgradeResourceProvider(AmbariManagementController managementController);
 
+  @Named("ambariConfiguration")
+  ResourceProvider getAmbariConfigurationResourceProvider();
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/642b5780/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 b35b2a8..95d33cf 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
@@ -254,6 +254,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
         return new ClusterKerberosDescriptorResourceProvider(managementController);
       case LoggingQuery:
         return new LoggingResourceProvider(propertyIds, keyPropertyIds, managementController);
+      case AmbariConfiguration:
+        return resourceProviderFactory.getAmbariConfigurationResourceProvider();
       default:
         throw new IllegalArgumentException("Unknown type " + type);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/642b5780/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
index e8f186d..2302d8b 100644
--- 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
@@ -25,7 +25,6 @@ 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;
@@ -46,11 +45,11 @@ import org.slf4j.LoggerFactory;
 import com.google.common.collect.Sets;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import com.google.inject.assistedinject.AssistedInject;
 
 /**
  * Resource provider for AmbariConfiguration resources.
  */
-@StaticallyInject
 public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResourceProvider {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(AmbariConfigurationResourceProvider.class);
@@ -60,7 +59,7 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
   /**
    * Resource property id constants.
    */
-  private enum ResourcePropertyId {
+  public enum ResourcePropertyId {
 
     ID("AmbariConfiguration/id"),
     TYPE("AmbariConfiguration/type"),
@@ -112,11 +111,12 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
 
 
   @Inject
-  private static AmbariConfigurationDAO ambariConfigurationDAO;
+  private AmbariConfigurationDAO ambariConfigurationDAO;
 
   private Gson gson;
 
-  protected AmbariConfigurationResourceProvider() {
+  @AssistedInject
+  public AmbariConfigurationResourceProvider() {
     super(PROPERTIES, PK_PROPERTY_MAP);
     setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION));
     setRequiredDeleteAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION));
@@ -134,7 +134,12 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
     ResourceAlreadyExistsException, NoSuchParentResourceException {
 
     LOGGER.info("Creating new ambari configuration resource ...");
-    AmbariConfigurationEntity ambariConfigurationEntity = getEntityFromRequest(request);
+    AmbariConfigurationEntity ambariConfigurationEntity = null;
+    try {
+      ambariConfigurationEntity = getEntityFromRequest(request);
+    } catch (AmbariException e) {
+      throw new NoSuchParentResourceException(e.getMessage());
+    }
 
     LOGGER.info("Persisting new ambari configuration: {} ", ambariConfigurationEntity);
     ambariConfigurationDAO.create(ambariConfigurationEntity);
@@ -148,6 +153,7 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
     UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
     Set<Resource> resources = Sets.newHashSet();
 
+    // retrieves allconfigurations, filtering is done at a higher level
     List<AmbariConfigurationEntity> ambariConfigurationEntities = ambariConfigurationDAO.findAll();
     for (AmbariConfigurationEntity ambariConfigurationEntity : ambariConfigurationEntities) {
       try {
@@ -181,40 +187,86 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
 
   }
 
+  @Override
+  protected RequestStatus updateResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
+    UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    Long idFromRequest = Long.valueOf((String) PredicateHelper.getProperties(predicate).get(ResourcePropertyId.ID.getPropertyId()));
+
+    AmbariConfigurationEntity persistedEntity = ambariConfigurationDAO.findByPK(idFromRequest);
+    if (persistedEntity == null) {
+      String errorMsg = String.format("Entity with primary key [ %s ] not found in the database.", idFromRequest);
+      LOGGER.error(errorMsg);
+      throw new NoSuchResourceException(errorMsg);
+    }
+
+    try {
+
+      AmbariConfigurationEntity entityFromRequest = getEntityFromRequest(request);
+      persistedEntity.getConfigurationBaseEntity().setVersionTag(entityFromRequest.getConfigurationBaseEntity().getVersionTag());
+      persistedEntity.getConfigurationBaseEntity().setVersion(entityFromRequest.getConfigurationBaseEntity().getVersion());
+      persistedEntity.getConfigurationBaseEntity().setType(entityFromRequest.getConfigurationBaseEntity().getType());
+      persistedEntity.getConfigurationBaseEntity().setConfigurationData(entityFromRequest.getConfigurationBaseEntity().getConfigurationData());
+      persistedEntity.getConfigurationBaseEntity().setConfigurationAttributes(entityFromRequest.getConfigurationBaseEntity().getConfigurationAttributes());
+
+
+      ambariConfigurationDAO.create(persistedEntity);
+    } catch (AmbariException e) {
+      throw new NoSuchParentResourceException(e.getMessage());
+    }
+
+    return getRequestStatus(null);
+
+  }
+
   private Resource toResource(AmbariConfigurationEntity entity, Set<String> requestedIds) throws AmbariException {
+
+    if (null == entity) {
+      throw new IllegalArgumentException("Null entity can't be transformed into a resource");
+    }
+
+    if (null == entity.getConfigurationBaseEntity()) {
+      throw new IllegalArgumentException("Invalid configuration entity can't be transformed into a resource");
+    }
     Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
     Set<Map<String, String>> 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);
+    setResourceProperty(resource, ResourcePropertyId.VERSION.getPropertyId(), entity.getConfigurationBaseEntity().getVersion(), requestedIds);
+    setResourceProperty(resource, ResourcePropertyId.VERSION_TAG.getPropertyId(), entity.getConfigurationBaseEntity().getVersionTag(), requestedIds);
 
     return resource;
   }
 
-  private AmbariConfigurationEntity getEntityFromRequest(Request request) {
+  private AmbariConfigurationEntity getEntityFromRequest(Request request) throws AmbariException {
 
     AmbariConfigurationEntity ambariConfigurationEntity = new AmbariConfigurationEntity();
     ambariConfigurationEntity.setConfigurationBaseEntity(new ConfigurationBaseEntity());
 
+    // set of resource properties (eache entry in the set belongs to a different resource)
+    Set<Map<String, Object>> resourcePropertiesSet = request.getProperties();
+
+    if (resourcePropertiesSet.size() != 1) {
+      throw new AmbariException("There must be only one resource specified in the request");
+    }
+
 
     for (ResourcePropertyId resourcePropertyId : ResourcePropertyId.values()) {
-      Object requestValue = getValueFromRequest(resourcePropertyId, request);
+      Object requestValue = getValueFromResourceProperties(resourcePropertyId, resourcePropertiesSet.iterator().next());
 
       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);
+          Integer version = (requestValue == null) ? DEFAULT_VERSION : Integer.valueOf((String) requestValue);
           ambariConfigurationEntity.getConfigurationBaseEntity().setVersion((version));
           break;
         case VERSION_TAG:
@@ -231,15 +283,13 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
 
   }
 
-  private Object getValueFromRequest(ResourcePropertyId resourcePropertyIdEnum, Request request) {
-    LOGGER.debug("Locating resource property [{}] in the request ...", resourcePropertyIdEnum);
+  private Object getValueFromResourceProperties(ResourcePropertyId resourcePropertyIdEnum, Map<String, Object> resourceProperties) {
+    LOGGER.debug("Locating resource property [{}] in the resource properties map ...", resourcePropertyIdEnum);
     Object requestValue = null;
-    for (Map<String, Object> 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;
-      }
+
+    if (resourceProperties.containsKey(resourcePropertyIdEnum.getPropertyId())) {
+      requestValue = resourceProperties.get(resourcePropertyIdEnum.getPropertyId());
+      LOGGER.debug("Found resource property {} in the resource properties map, value: {}", resourcePropertyIdEnum, requestValue);
     }
     return requestValue;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/642b5780/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 6e7ca0a..95c7b83 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
@@ -122,8 +122,6 @@ 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,

http://git-wip-us.apache.org/repos/asf/ambari/blob/642b5780/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
index c29a423..5710a7f 100644
--- 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
@@ -19,8 +19,11 @@ import javax.inject.Singleton;
 
 import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
 
+import com.google.inject.persist.Transactional;
+
 /**
  * DAO dealing with ambari configuration related JPA operations.
+ * Operations delegate to the JPA provider implementation of CRUD operations.
  */
 
 @Singleton
@@ -31,6 +34,7 @@ public class AmbariConfigurationDAO extends CrudDAO<AmbariConfigurationEntity, L
     super(AmbariConfigurationEntity.class);
   }
 
+  @Transactional
   public void create(AmbariConfigurationEntity entity) {
     super.create(entity);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/642b5780/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProviderTest.java
new file mode 100644
index 0000000..d974682
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProviderTest.java
@@ -0,0 +1,231 @@
+/*
+ * 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.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+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.easymock.Capture;
+import org.easymock.EasyMock;
+import org.easymock.EasyMockRule;
+import org.easymock.EasyMockSupport;
+import org.easymock.Mock;
+import org.easymock.TestSubject;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class AmbariConfigurationResourceProviderTest extends EasyMockSupport {
+
+  @Rule
+  public EasyMockRule mocks = new EasyMockRule(this);
+
+  @Mock
+  private Request requestMock;
+
+  @Mock
+  private AmbariConfigurationDAO ambariConfigurationDAO;
+
+  private Capture<AmbariConfigurationEntity> ambariConfigurationEntityCapture;
+
+  private Gson gson;
+
+  private static final String DATA_MOCK_STR = "[\n" +
+    "      {\n" +
+    "        \"authentication.ldap.baseDn\" : \"dc=ambari,dc=apache,dc=org\",\n" +
+    "        \"authentication.ldap.primaryUrl\" : \"localhost:33389\",\n" +
+    "        \"authentication.ldap.secondaryUrl\" : \"localhost:333\"\n" +
+    "      }\n" +
+    "    ]";
+
+  private static final Long PK_LONG = Long.valueOf(1);
+  private static final String PK_STRING = String.valueOf(1);
+  private static final String VERSION_TAG = "test version";
+  private static final String VERSION = "1";
+
+  @TestSubject
+  private AmbariConfigurationResourceProvider ambariConfigurationResourceProvider = new AmbariConfigurationResourceProvider();
+
+  @Before
+  public void setup() {
+    ambariConfigurationEntityCapture = Capture.newInstance();
+    gson = new GsonBuilder().create();
+  }
+
+  @Test
+  public void testCreateAmbariConfigurationRequestResultsInTheProperPersistenceCall() throws Exception {
+
+    // GIVEN
+    // configuration properties parsed from the request
+    Set<Map<String, Object>> resourcePropertiesSet = Sets.newHashSet(
+      new PropertiesMapBuilder()
+        .withId(PK_LONG)
+        .withVersion(VERSION)
+        .withVersionTag(VERSION_TAG)
+        .withData(DATA_MOCK_STR)
+        .build());
+
+    // mock the request to return the properties
+    EasyMock.expect(requestMock.getProperties()).andReturn(resourcePropertiesSet);
+
+    // capture the entity the DAO gets called with
+    ambariConfigurationDAO.create(EasyMock.capture(ambariConfigurationEntityCapture));
+    replayAll();
+
+    // WHEN
+    ambariConfigurationResourceProvider.createResourcesAuthorized(requestMock);
+
+    // THEN
+    AmbariConfigurationEntity capturedAmbariConfigurationEntity = ambariConfigurationEntityCapture.getValue();
+    Assert.assertNotNull(capturedAmbariConfigurationEntity);
+    Assert.assertNull("The entity identifier should be null", capturedAmbariConfigurationEntity.getId());
+    Assert.assertEquals("The entity version is not the expected", Integer.valueOf(VERSION),
+      capturedAmbariConfigurationEntity.getConfigurationBaseEntity().getVersion());
+    Assert.assertEquals("The entity version tag is not the expected", VERSION_TAG,
+      capturedAmbariConfigurationEntity.getConfigurationBaseEntity().getVersionTag());
+    Assert.assertEquals("The entity data is not the expected", DATA_MOCK_STR,
+      gson.fromJson(capturedAmbariConfigurationEntity.getConfigurationBaseEntity().getConfigurationData(), String.class));
+  }
+
+  @Test
+  public void testRemoveAmbariConfigurationRequestResultsInTheProperPersistenceCall() throws Exception {
+    // GIVEN
+    Predicate predicate = new PredicateBuilder().property(
+      AmbariConfigurationResourceProvider.ResourcePropertyId.ID.getPropertyId()).equals("1").toPredicate();
+
+    Capture<Long> pkCapture = Capture.newInstance();
+    ambariConfigurationDAO.removeByPK(EasyMock.capture(pkCapture));
+    replayAll();
+
+    // WHEN
+    ambariConfigurationResourceProvider.deleteResourcesAuthorized(requestMock, predicate);
+
+    // THEN
+    Assert.assertEquals("The pk of the entity to be removed doen't match the expected id", Long.valueOf(1), pkCapture.getValue());
+  }
+
+
+  @Test
+  public void testRetrieveAmbariConfigurationShouldResultsInTheProperDAOCall() throws Exception {
+    // GIVEN
+    Predicate predicate = new PredicateBuilder().property(
+      AmbariConfigurationResourceProvider.ResourcePropertyId.ID.getPropertyId()).equals("1").toPredicate();
+
+    EasyMock.expect(ambariConfigurationDAO.findAll()).andReturn(Lists.newArrayList(createDummyAmbariConfigurationEntity()));
+    replayAll();
+
+    // WHEN
+    Set<Resource> resourceSet = ambariConfigurationResourceProvider.getResourcesAuthorized(requestMock, predicate);
+
+    // THEN
+    Assert.assertNotNull(resourceSet);
+    Assert.assertFalse(resourceSet.isEmpty());
+  }
+
+  @Test
+  public void testUpdateAmbariConfigurationShouldResultInTheProperDAOCalls() throws Exception {
+    // GIVEN
+
+    Predicate predicate = new PredicateBuilder().property(
+      AmbariConfigurationResourceProvider.ResourcePropertyId.ID.getPropertyId()).equals("1").toPredicate();
+
+    // properteies in the request, representing the updated configuration
+    Set<Map<String, Object>> resourcePropertiesSet = Sets.newHashSet(new PropertiesMapBuilder()
+      .withId(PK_LONG)
+      .withVersion("2")
+      .withVersionTag("version-2")
+      .withData(DATA_MOCK_STR).build());
+
+    EasyMock.expect(requestMock.getProperties()).andReturn(resourcePropertiesSet);
+
+    AmbariConfigurationEntity persistedEntity = createDummyAmbariConfigurationEntity();
+    EasyMock.expect(ambariConfigurationDAO.findByPK(PK_LONG)).andReturn(persistedEntity);
+    ambariConfigurationDAO.create(EasyMock.capture(ambariConfigurationEntityCapture));
+
+    replayAll();
+
+    // WHEN
+    ambariConfigurationResourceProvider.updateResourcesAuthorized(requestMock, predicate);
+
+    // the captured entity should be the updated one
+    AmbariConfigurationEntity updatedEntity = ambariConfigurationEntityCapture.getValue();
+
+    // THEN
+    Assert.assertNotNull(updatedEntity);
+    Assert.assertEquals("The updated version is wrong", Integer.valueOf(2), updatedEntity.getConfigurationBaseEntity().getVersion());
+  }
+
+  private class PropertiesMapBuilder {
+
+    private Map<String, Object> resourcePropertiesMap = Maps.newHashMap();
+
+    private PropertiesMapBuilder() {
+    }
+
+    public PropertiesMapBuilder withId(Long id) {
+      resourcePropertiesMap.put(AmbariConfigurationResourceProvider.ResourcePropertyId.ID.getPropertyId(), id);
+      return this;
+    }
+
+    private PropertiesMapBuilder withVersion(String version) {
+      resourcePropertiesMap.put(AmbariConfigurationResourceProvider.ResourcePropertyId.VERSION.getPropertyId(), version);
+      return this;
+    }
+
+    private PropertiesMapBuilder withVersionTag(String versionTag) {
+      resourcePropertiesMap.put(AmbariConfigurationResourceProvider.ResourcePropertyId.VERSION_TAG.getPropertyId(), versionTag);
+      return this;
+    }
+
+    private PropertiesMapBuilder withData(String dataJson) {
+      resourcePropertiesMap.put(AmbariConfigurationResourceProvider.ResourcePropertyId.DATA.getPropertyId(), dataJson);
+      return this;
+    }
+
+    public Map<String, Object> build() {
+      return this.resourcePropertiesMap;
+    }
+
+  }
+
+  private AmbariConfigurationEntity createDummyAmbariConfigurationEntity() {
+    AmbariConfigurationEntity acEntity = new AmbariConfigurationEntity();
+    ConfigurationBaseEntity configurationBaseEntity = new ConfigurationBaseEntity();
+    acEntity.setConfigurationBaseEntity(configurationBaseEntity);
+    acEntity.setId(PK_LONG);
+    acEntity.getConfigurationBaseEntity().setConfigurationData(DATA_MOCK_STR);
+    acEntity.getConfigurationBaseEntity().setVersion(Integer.valueOf(VERSION));
+    acEntity.getConfigurationBaseEntity().setVersionTag(VERSION_TAG);
+    acEntity.getConfigurationBaseEntity().setType("ldap-config");
+
+    return acEntity;
+  }
+
+
+}
\ No newline at end of file


[21/38] ambari git commit: AMBARI-21952 : Refine AMS heap recommendations in stack advisor. (avijayan)

Posted by lp...@apache.org.
AMBARI-21952 : Refine AMS heap recommendations in stack advisor. (avijayan)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6c40fdf4
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6c40fdf4
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6c40fdf4

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 6c40fdf48e21db493d3449ba59e652f90e264ec3
Parents: 7a7d232
Author: Aravindan Vijayan <av...@hortonworks.com>
Authored: Wed Sep 13 15:14:12 2017 -0700
Committer: Aravindan Vijayan <av...@hortonworks.com>
Committed: Wed Sep 13 15:14:12 2017 -0700

----------------------------------------------------------------------
 .../stacks/HDP/2.0.6/services/stack_advisor.py  |  81 +++----
 .../stacks/2.0.6/common/test_stack_advisor.py   |   4 +-
 .../stacks/2.2/common/test_stack_advisor.py     | 232 +++++++++++++++++--
 3 files changed, 257 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/6c40fdf4/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
index 70cb7a2..0249ea2 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
@@ -517,18 +517,22 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
     schMemoryMap = {
       "HDFS": {
         "NAMENODE": HEAP_PER_MASTER_COMPONENT,
+        "SECONDARY_NAMENODE": HEAP_PER_MASTER_COMPONENT,
         "DATANODE": HEAP_PER_SLAVE_COMPONENT
       },
       "YARN": {
         "RESOURCEMANAGER": HEAP_PER_MASTER_COMPONENT,
+        "NODEMANAGER": HEAP_PER_SLAVE_COMPONENT,
+        "HISTORYSERVER" : HEAP_PER_MASTER_COMPONENT,
+        "APP_TIMELINE_SERVER": HEAP_PER_MASTER_COMPONENT
       },
       "HBASE": {
         "HBASE_MASTER": HEAP_PER_MASTER_COMPONENT,
         "HBASE_REGIONSERVER": HEAP_PER_SLAVE_COMPONENT
       },
-      "ACCUMULO": {
-        "ACCUMULO_MASTER": HEAP_PER_MASTER_COMPONENT,
-        "ACCUMULO_TSERVER": HEAP_PER_SLAVE_COMPONENT
+      "HIVE": {
+        "HIVE_METASTORE": HEAP_PER_MASTER_COMPONENT,
+        "HIVE_SERVER": HEAP_PER_MASTER_COMPONENT
       },
       "KAFKA": {
         "KAFKA_BROKER": HEAP_PER_MASTER_COMPONENT
@@ -542,6 +546,13 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
       "AMBARI_METRICS": {
         "METRICS_COLLECTOR": HEAP_PER_MASTER_COMPONENT,
         "METRICS_MONITOR": HEAP_PER_SLAVE_COMPONENT
+      },
+      "ACCUMULO": {
+        "ACCUMULO_MASTER": HEAP_PER_MASTER_COMPONENT,
+        "ACCUMULO_TSERVER": HEAP_PER_SLAVE_COMPONENT
+      },
+      "LOGSEARCH": {
+        "LOGSEARCH_LOGFEEDER" : HEAP_PER_SLAVE_COMPONENT
       }
     }
     total_sinks_count = 0
@@ -552,9 +563,10 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
         schCount = len(
           self.getHostsWithComponent(serviceName, componentName, services,
                                      hosts))
-        hbase_heapsize += int((schCount * multiplier) ** 0.9)
+        hbase_heapsize += int((schCount * multiplier))
         total_sinks_count += schCount
-    collector_heapsize = int(hbase_heapsize/4 if hbase_heapsize > 2048 else 512)
+    collector_heapsize = int(hbase_heapsize/3 if hbase_heapsize > 2048 else 512)
+    hbase_heapsize = min(hbase_heapsize, 32768)
 
     return round_to_n(collector_heapsize), round_to_n(hbase_heapsize), total_sinks_count
 
@@ -679,7 +691,7 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
         putAmsHbaseSiteProperty("phoenix.coprocessor.maxMetaDataCacheSize", 81920000)
         putAmsSiteProperty("phoenix.query.maxGlobalMemoryPercentage", 30)
         putAmsSiteProperty("timeline.metrics.service.resultset.fetchSize", 10000)
-      elif total_sinks_count >= 500:
+      elif total_sinks_count >= 1000:
         putAmsHbaseSiteProperty("hbase.regionserver.handler.count", 60)
         putAmsHbaseSiteProperty("hbase.regionserver.hlog.blocksize", 134217728)
         putAmsHbaseSiteProperty("hbase.regionserver.maxlogs", 64)
@@ -695,17 +707,17 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
 
     # Distributed mode heap size
     if operatingMode == "distributed":
-      hbase_heapsize = max(hbase_heapsize, 768)
+      hbase_heapsize = max(hbase_heapsize, 1024)
       putHbaseEnvProperty("hbase_master_heapsize", "512")
       putHbaseEnvProperty("hbase_master_xmn_size", "102") #20% of 512 heap size
       putHbaseEnvProperty("hbase_regionserver_heapsize", hbase_heapsize)
-      putHbaseEnvProperty("regionserver_xmn_size", round_to_n(0.15*hbase_heapsize,64))
+      putHbaseEnvProperty("regionserver_xmn_size", round_to_n(0.15 * hbase_heapsize,64))
     else:
       # Embedded mode heap size : master + regionserver
-      hbase_rs_heapsize = 768
+      hbase_rs_heapsize = 512
       putHbaseEnvProperty("hbase_regionserver_heapsize", hbase_rs_heapsize)
       putHbaseEnvProperty("hbase_master_heapsize", hbase_heapsize)
-      putHbaseEnvProperty("hbase_master_xmn_size", round_to_n(0.15*(hbase_heapsize+hbase_rs_heapsize),64))
+      putHbaseEnvProperty("hbase_master_xmn_size", round_to_n(0.15*(hbase_heapsize + hbase_rs_heapsize),64))
 
     # If no local DN in distributed mode
     if operatingMode == "distributed":
@@ -832,6 +844,12 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
       pass
     elif len(self.getComponentHostNames(services, "AMBARI_METRICS", "METRICS_COLLECTOR")) > 1 and op_mode != 'distributed':
       correct_op_mode_item = self.getErrorItem("Correct value should be 'distributed' for clusters with more then 1 Metrics collector")
+    elif op_mode == 'embedded':
+      collector_heapsize, hbase_heapsize, total_sinks_count = self.getAmsMemoryRecommendation(services, hosts)
+      if total_sinks_count > 1000:
+        correct_op_mode_item = self.getWarnItem("Number of sinks writing metrics to collector is expected to be more than 1000. "
+                                                "'Embedded' mode AMS might not be able to handle the load. Consider moving to distributed mode.")
+
     validationItems.extend([{"config-name":'timeline.metrics.service.operation.mode', "item": correct_op_mode_item }])
     return self.toConfigurationValidationProblems(validationItems, "ams-site")
 
@@ -1003,6 +1021,11 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
     is_hbase_distributed = amsHbaseSite.get("hbase.cluster.distributed").lower() == 'true'
 
     if is_hbase_distributed:
+
+      if not regionServerItem and hbase_regionserver_heapsize > 32768:
+        regionServerItem = self.getWarnItem("Value is more than the recommended maximum heap size of 32G.")
+        validationItems.extend([{"config-name": "hbase_regionserver_heapsize", "item": regionServerItem}])
+
       minMasterXmn = 0.12 * hbase_master_heapsize
       maxMasterXmn = 0.2 * hbase_master_heapsize
       if hbase_master_xmn_size < minMasterXmn:
@@ -1025,6 +1048,11 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
                                                "(20% of hbase_regionserver_heapsize)"
                                                .format(int(floor(maxRegionServerXmn))))
     else:
+
+      if not hbaseMasterHeapsizeItem and (hbase_master_heapsize + hbase_regionserver_heapsize) > 32768:
+        hbaseMasterHeapsizeItem = self.getWarnItem("Value of Master + Regionserver heapsize is more than the recommended maximum heap size of 32G.")
+        validationItems.extend([{"config-name": "hbase_master_heapsize", "item": hbaseMasterHeapsizeItem}])
+
       minMasterXmn = 0.12 * (hbase_master_heapsize + hbase_regionserver_heapsize)
       maxMasterXmn = 0.2 *  (hbase_master_heapsize + hbase_regionserver_heapsize)
       if hbase_master_xmn_size < minMasterXmn:
@@ -1071,39 +1099,6 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
                   collectorHostName, str(", ".join(hostMasterComponents[collectorHostName]))))
               if hbaseMasterHeapsizeItem:
                 validationItems.extend([{"config-name": "hbase_master_heapsize", "item": hbaseMasterHeapsizeItem}])
-
-            # Check for unused RAM on AMS Collector node
-            hostComponents = []
-            for service in services["services"]:
-              for component in service["components"]:
-                if component["StackServiceComponents"]["hostnames"] is not None:
-                  if collectorHostName in component["StackServiceComponents"]["hostnames"]:
-                    hostComponents.append(component["StackServiceComponents"]["component_name"])
-
-            requiredMemory = self.getMemorySizeRequired(services, hostComponents, configurations)
-            unusedMemory = host["Hosts"]["total_mem"] * 1024 - requiredMemory # in bytes
-
-            heapPropertyToIncrease = "hbase_regionserver_heapsize" if is_hbase_distributed else "hbase_master_heapsize"
-            xmnPropertyToIncrease = "regionserver_xmn_size" if is_hbase_distributed else "hbase_master_xmn_size"
-            hbase_needs_increase = self.to_number(properties[heapPropertyToIncrease]) * mb < 32 * gb
-
-            if unusedMemory > 4*gb and hbase_needs_increase:  # warn user, if more than 4GB RAM is unused
-
-              recommended_hbase_heapsize = int((unusedMemory - 4*gb)*4/5) + self.to_number(properties.get(heapPropertyToIncrease))*mb
-              recommended_hbase_heapsize = min(32*gb, recommended_hbase_heapsize) #Make sure heapsize <= 32GB
-              recommended_hbase_heapsize = round_to_n(recommended_hbase_heapsize/mb,128) # Round to 128m multiple
-              if self.to_number(properties[heapPropertyToIncrease]) < recommended_hbase_heapsize:
-                hbaseHeapsizeItem = self.getWarnItem("Consider allocating {0} MB to {1} in ams-hbase-env to use up some "
-                                                     "unused memory on host"
-                                                         .format(recommended_hbase_heapsize,
-                                                                 heapPropertyToIncrease))
-                validationItems.extend([{"config-name": heapPropertyToIncrease, "item": hbaseHeapsizeItem}])
-
-              recommended_xmn_size = round_to_n(0.15*recommended_hbase_heapsize,128)
-              if self.to_number(properties[xmnPropertyToIncrease]) < recommended_xmn_size:
-                xmnPropertyToIncreaseItem = self.getWarnItem("Consider allocating {0} MB to use up some unused memory "
-                                                             "on host".format(recommended_xmn_size))
-                validationItems.extend([{"config-name": xmnPropertyToIncrease, "item": xmnPropertyToIncreaseItem}])
       pass
 
     return self.toConfigurationValidationProblems(validationItems, "ams-hbase-env")

http://git-wip-us.apache.org/repos/asf/ambari/blob/6c40fdf4/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py b/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
index 0c4996b..65b23b0 100644
--- a/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
+++ b/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
@@ -2410,7 +2410,7 @@ class TestHDP206StackAdvisor(TestCase):
                   'ams-hbase-env': {'properties': {'hbase_log_dir': '/var/log/ambari-metrics-collector',
                                                                                        'hbase_master_heapsize': '512',
                                                                                        'hbase_master_xmn_size': '102',
-                                                                                       'hbase_regionserver_heapsize': '768',
+                                                                                       'hbase_regionserver_heapsize': '1024',
                                                                                        'regionserver_xmn_size': '128'}},
                   'ams-hbase-site': {'properties': {'hbase.cluster.distributed': 'true',
                                                                                          'hbase.hregion.memstore.flush.size': '134217728',
@@ -2475,7 +2475,7 @@ class TestHDP206StackAdvisor(TestCase):
                   'ams-hbase-env': {'properties': {'hbase_log_dir': '/var/log/ambari-metrics-collector',
                                                                                        'hbase_master_heapsize': '512',
                                                                                        'hbase_master_xmn_size': '102',
-                                                                                       'hbase_regionserver_heapsize': '768',
+                                                                                       'hbase_regionserver_heapsize': '1024',
                                                                                        'regionserver_xmn_size': '128'}},
                   'ams-hbase-site': {'properties': {'hbase.cluster.distributed': 'true',
                                                                                          'hbase.hregion.memstore.flush.size': '134217728',

http://git-wip-us.apache.org/repos/asf/ambari/blob/6c40fdf4/ambari-server/src/test/python/stacks/2.2/common/test_stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.2/common/test_stack_advisor.py b/ambari-server/src/test/python/stacks/2.2/common/test_stack_advisor.py
index 571ff26..d6b572e 100644
--- a/ambari-server/src/test/python/stacks/2.2/common/test_stack_advisor.py
+++ b/ambari-server/src/test/python/stacks/2.2/common/test_stack_advisor.py
@@ -2338,9 +2338,9 @@ class TestHDP22StackAdvisor(TestCase):
     expected = {
       "ams-hbase-env": {
         "properties": {
-          "hbase_master_xmn_size": "192",
+          "hbase_master_xmn_size": "128",
           "hbase_master_heapsize": "512",
-          "hbase_regionserver_heapsize": "768"
+          "hbase_regionserver_heapsize": "512"
         }
       },
       "ams-grafana-env": {
@@ -2416,14 +2416,14 @@ class TestHDP22StackAdvisor(TestCase):
 
     expected["ams-site"]['properties']['timeline.metrics.cache.size'] = '500'
     expected["ams-site"]['properties']['timeline.metrics.cache.commit.interval'] = '7'
-    expected["ams-hbase-env"]['properties']['hbase_master_heapsize'] = '1408'
-    expected["ams-hbase-env"]['properties']['hbase_master_xmn_size'] = '320'
-    expected["ams-env"]['properties']['metrics_collector_heapsize'] = '512'
+    expected["ams-hbase-env"]['properties']['hbase_master_heapsize'] = '2560'
+    expected["ams-hbase-env"]['properties']['hbase_master_xmn_size'] = '448'
+    expected["ams-env"]['properties']['metrics_collector_heapsize'] = '896'
 
     self.stackAdvisor.recommendAmsConfigurations(configurations, clusterData, services, hosts)
     self.assertEquals(configurations, expected)
 
-    # Still 100 nodes, but with HDFS and YARN services installed on all nodes
+    # 200 nodes, but with HDFS and YARN services installed on all nodes
     services['services'] = [
       {
         "StackServices": {
@@ -2484,14 +2484,22 @@ class TestHDP22StackAdvisor(TestCase):
       }
 
     ]
-    expected["ams-site"]['properties']['timeline.metrics.host.aggregate.splitpoints'] = 'mem_total'
+    expected["ams-site"]['properties']['timeline.metrics.host.aggregate.splitpoints'] = 'dfs.FSNamesystem.FilesTotal,' \
+                                                                                        'dfs.datanode.WritesFromRemoteClient,' \
+                                                                                        'ipc.IPC.numCallsInReplicationQueue,' \
+                                                                                        'mapred.ShuffleMetrics.ShuffleOutputsFailed,' \
+                                                                                        'mem_buffered,' \
+                                                                                        'read_count,' \
+                                                                                        'regionserver.Server.percentFilesLocal,' \
+                                                                                        'rpcdetailed.rpcdetailed.RegisterNodeManagerNumOps,' \
+                                                                                        'sdisk_vdb_write_count'
     expected["ams-site"]['properties']['timeline.metrics.cluster.aggregate.splitpoints'] = 'mem_total'
 
-    expected["ams-site"]['properties']['timeline.metrics.cache.size'] = '500'
-    expected["ams-site"]['properties']['timeline.metrics.cache.commit.interval'] = '7'
-    expected["ams-hbase-env"]['properties']['hbase_master_heapsize'] = '2432'
-    expected["ams-hbase-env"]['properties']['hbase_master_xmn_size'] = '512'
-    expected["ams-env"]['properties']['metrics_collector_heapsize'] = '640'
+    expected["ams-site"]['properties']['timeline.metrics.cache.size'] = '600'
+    expected["ams-site"]['properties']['timeline.metrics.cache.commit.interval'] = '6'
+    expected["ams-hbase-env"]['properties']['hbase_master_heapsize'] = '6656'
+    expected["ams-hbase-env"]['properties']['hbase_master_xmn_size'] = '1088'
+    expected["ams-env"]['properties']['metrics_collector_heapsize'] = '2176'
 
     self.stackAdvisor.recommendAmsConfigurations(configurations, clusterData, services, hosts)
     self.assertEquals(configurations, expected)
@@ -2535,6 +2543,7 @@ class TestHDP22StackAdvisor(TestCase):
     self.stackAdvisor.recommendAmsConfigurations(configurations, clusterData, services, hosts)
     self.assertEquals(configurations, expected)
 
+
     # Embedded mode, 8192m master heapsize, more splitpoints recommended
     services["configurations"]['ams-hbase-env']['properties']['hbase_master_heapsize'] = '8192'
     expected['ams-hbase-env']['properties']['hbase_master_heapsize'] = '8192'
@@ -2559,12 +2568,11 @@ class TestHDP22StackAdvisor(TestCase):
     expected['ams-hbase-site']['properties']['dfs.client.read.shortcircuit'] = 'true'
 
     # Distributed mode, low memory, no splitpoints recommended
-    services["configurations"]['ams-hbase-env']['properties']['hbase_regionserver_heapsize'] = '512'
     expected['ams-site']['properties']['timeline.metrics.host.aggregate.splitpoints'] = 'mem_total'
     expected['ams-site']['properties']['timeline.metrics.cluster.aggregate.splitpoints'] = 'mem_total'
-    expected['ams-hbase-env']['properties']['hbase_regionserver_heapsize'] = '512'
+    expected['ams-hbase-env']['properties']['hbase_regionserver_heapsize'] = '6656'
     expected["ams-hbase-env"]['properties']['hbase_master_xmn_size'] = '102'
-    expected['ams-hbase-env']['properties']['regionserver_xmn_size'] = '384'
+    expected['ams-hbase-env']['properties']['regionserver_xmn_size'] = '1024'
     expected['ams-site']['properties']['timeline.metrics.service.watcher.disabled'] = 'true'
     self.stackAdvisor.recommendAmsConfigurations(configurations, clusterData, services, hosts)
     self.assertEquals(configurations, expected)
@@ -2610,6 +2618,200 @@ class TestHDP22StackAdvisor(TestCase):
     self.assertEquals(configurations["ams-site"]['properties']['timeline.metrics.cache.size'], '700')
     self.assertEquals(configurations["ams-site"]['properties']['timeline.metrics.cache.commit.interval'], '5')
 
+    # 500 Nodes with HDFS, YARN, HIVE, STORM, HBASE, KAFKA, AMS
+    node_count = 500
+    hosts = {
+      "items": []
+    }
+    for i in range(1, node_count):
+      hosts['items'].extend([{
+        "Hosts": {
+          "host_name": "host" + str(i)
+          }
+      }])
+
+    services['services'] = [
+      {
+        "StackServices": {
+          "service_name": "HDFS"
+        },
+        "components": [
+          {
+            "StackServiceComponents": {
+              "component_name": "NAMENODE",
+              "hostnames": ["host1"]
+            }
+          } ,
+          {
+            "StackServiceComponents": {
+              "component_name": "SECONDARY_NAMENODE",
+              "hostnames": ["host2"]
+            }
+          },
+          {
+            "StackServiceComponents": {
+              "component_name": "DATANODE",
+              "hostnames": ["host" + str(i) for i in range(6, node_count + 1)]
+            }
+          }
+        ]
+      },
+      {
+        "StackServices": {
+          "service_name": "HBASE"
+        },
+        "components": [
+          {
+            "StackServiceComponents": {
+              "component_name": "HBASE_MASTER",
+              "hostnames": ["host3"]
+            }
+          },
+          {
+            "StackServiceComponents": {
+              "component_name": "HBASE_REGIONSERVER",
+              "hostnames": ["host" + str(i) for i in range(6, node_count + 1)]
+            }
+          }
+        ]
+      },
+      {
+        "StackServices": {
+          "service_name": "YARN"
+        },
+        "components": [
+          {
+            "StackServiceComponents": {
+              "component_name": "RESOURCEMANAGER",
+              "hostnames": ["host4"]
+            }
+          },
+          {
+            "StackServiceComponents": {
+              "component_name": "NODEMANAGER",
+              "hostnames": ["host" + str(i) for i in range(6, node_count + 1)]
+            }
+          }
+        ]
+      },
+      {
+        "StackServices": {
+          "service_name": "HIVE"
+        },
+        "components": [
+          {
+            "StackServiceComponents": {
+              "component_name": "HIVE_METASTORE",
+              "hostnames": ["host3"]
+            }
+          },
+          {
+            "StackServiceComponents": {
+              "component_name": "HIVE_SERVER",
+              "hostnames": ["host3"]
+            }
+          }
+        ]
+      },
+      {
+        "StackServices": {
+          "service_name": "STORM"
+        },
+        "components": [
+          {
+            "StackServiceComponents": {
+              "component_name": "NIMBUS",
+              "hostnames": ["host" + str(i) for i in range(1, 6)]
+            }
+          }
+        ]
+      },
+      {
+        "StackServices": {
+          "service_name": "KAFKA"
+        },
+        "components": [
+          {
+            "StackServiceComponents": {
+              "component_name": "KAFKA_BROKER",
+              "hostnames": ["host" + str(i) for i in range(1, 6)]
+            }
+          }
+        ]
+      },
+      {
+        "StackServices": {
+          "service_name": "AMBARI_METRICS"
+        },
+        "components": [
+          {
+            "StackServiceComponents": {
+              "component_name": "METRICS_COLLECTOR",
+              "hostnames": ["host6"]
+            }
+          },
+          {
+            "StackServiceComponents": {
+              "component_name": "METRICS_MONITOR",
+              "hostnames": ["host" + str(i) for i in range(6, node_count + 1)]
+            }
+          }
+        ]
+      }
+    ]
+
+    services['configurations'] = {
+      'core-site': {'properties': {}},
+      'ams-site': {'properties': {}},
+      'ams-hbase-site': {'properties': {}},
+      'ams-hbase-env': {'properties': {}}
+    }
+    services["configurations"]['ams-site']['properties']['timeline.metrics.service.operation.mode'] = 'distributed'
+
+    expected['ams-hbase-site']['properties']['hbase.cluster.distributed'] = 'true'
+    expected['ams-hbase-site']['properties']['hbase.rootdir'] = '/user/ams/hbase'
+    expected['ams-hbase-site']['properties']['hbase.zookeeper.property.clientPort'] = '2181'
+
+    expected["ams-site"]['properties']['timeline.metrics.host.aggregate.splitpoints'] = 'default.General.active_calls_api_get_all_databases,' \
+                                                                                        'default.General.api_get_database_mean,' \
+                                                                                        'default.General.gc.PS-MarkSweep.count,' \
+                                                                                        'dfs.FsVolume.TotalDataFileIos,' \
+                                                                                        'disk_free,' \
+                                                                                        'jvm.JvmMetrics.MemHeapMaxM,' \
+                                                                                        'kafka.network.RequestMetrics.RemoteTimeMs.request.Metadata.75percentile,' \
+                                                                                        'kafka.network.RequestMetrics.ResponseQueueTimeMs.request.Update.Metadata.mean,' \
+                                                                                        'load_one,master.FileSystem.MetaHlogSplitTime_75th_percentile,' \
+                                                                                        'metricssystem.MetricsSystem.NumActiveSources,' \
+                                                                                        'regionserver.Server.Append_95th_percentile,' \
+                                                                                        'regionserver.Server.blockCacheEvictionCount,' \
+                                                                                        'rpc.rpc.client.SentBytes,' \
+                                                                                        'sdisk_vda1_write_bytes'
+    expected["ams-site"]['properties']['timeline.metrics.cluster.aggregate.splitpoints'] = 'ipc.IPC.authorizationSuccesses,' \
+                                                                                           'metricssystem.MetricsSystem.PublishNumOps'
+
+    expected["ams-site"]['properties']['timeline.metrics.cache.size'] = '700'
+    expected["ams-site"]['properties']['timeline.metrics.cache.commit.interval'] = '5'
+    expected["ams-site"]['properties']['timeline.metrics.service.resultset.fetchSize'] = '5000'
+    expected["ams-site"]['properties']['phoenix.query.maxGlobalMemoryPercentage'] = '30'
+
+    expected["ams-env"]['properties']['metrics_collector_heapsize'] = '7040'
+
+    expected["ams-hbase-env"]['properties']['hbase_master_heapsize'] = '512'
+    expected["ams-hbase-env"]['properties']['hbase_master_xmn_size'] = '102'
+
+    expected["ams-hbase-env"]['properties']['hbase_regionserver_heapsize'] = '21120'
+    expected["ams-hbase-env"]['properties']['regionserver_xmn_size'] = '3200'
+
+    expected["ams-hbase-site"]['properties']['phoenix.query.maxGlobalMemoryPercentage'] = '20'
+    expected['ams-hbase-site']['properties']['hbase.hregion.memstore.flush.size'] = '268435456'
+    expected['ams-hbase-site']['properties']['hbase.regionserver.handler.count'] = '60'
+    expected['ams-hbase-site']['properties']['hbase.regionserver.hlog.blocksize'] = '134217728'
+    expected['ams-hbase-site']['properties']['hbase.regionserver.maxlogs'] = '64'
+    expected['ams-hbase-site']['properties']['phoenix.coprocessor.maxMetaDataCacheSize'] = '40960000'
+
+    self.stackAdvisor.recommendAmsConfigurations(configurations, clusterData, services, hosts)
+    self.assertEquals(configurations, expected)
+
   def test_recommendHbaseConfigurations(self):
     servicesList = ["HBASE"]
     configurations = {}


[16/38] ambari git commit: AMBARI-21946 Log Search UI: reorganize generated files structure. (ababiichuk)

Posted by lp...@apache.org.
AMBARI-21946 Log Search UI: reorganize generated files structure. (ababiichuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2a6dd58f
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2a6dd58f
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2a6dd58f

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 2a6dd58f506b5e9fcaf7b435e645c2397fe35855
Parents: 18ae06d
Author: ababiichuk <ab...@hortonworks.com>
Authored: Wed Sep 13 16:19:25 2017 +0300
Committer: ababiichuk <ab...@hortonworks.com>
Committed: Wed Sep 13 16:56:56 2017 +0300

----------------------------------------------------------------------
 .../ambari-logsearch-web/.angular-cli.json      |  34 +-
 ambari-logsearch/ambari-logsearch-web/README.md |  10 +-
 .../ambari-logsearch-web/package.json           |  34 +-
 ambari-logsearch/ambari-logsearch-web/pom.xml   |   1 +
 .../ambari-logsearch-web/src/app/app.module.ts  |   2 +-
 .../ambari-logsearch-web/webpack.config.js      | 530 +++++++++++++++++++
 6 files changed, 571 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/2a6dd58f/ambari-logsearch/ambari-logsearch-web/.angular-cli.json
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/.angular-cli.json b/ambari-logsearch/ambari-logsearch-web/.angular-cli.json
index 70fd7b6..267f5e0 100644
--- a/ambari-logsearch/ambari-logsearch-web/.angular-cli.json
+++ b/ambari-logsearch/ambari-logsearch-web/.angular-cli.json
@@ -1,12 +1,12 @@
 {
   "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
   "project": {
-    "name": "ambari-logsearch-web"
+    "name": "ambari-logsearch-web",
+    "ejected": true
   },
   "apps": [
     {
       "root": "src",
-      "outDir": "dist",
       "assets": [
         "assets",
         "favicon.ico"
@@ -15,20 +15,8 @@
       "main": "main.ts",
       "polyfills": "polyfills.ts",
       "test": "test.ts",
-      "tsconfig": "tsconfig.app.json",
       "testTsconfig": "tsconfig.spec.json",
-      "prefix": "app",
-      "styles": [
-        "styles.less",
-        "../node_modules/bootstrap/dist/css/bootstrap.min.css",
-        "../node_modules/font-awesome/css/font-awesome.min.css",
-        "../src/vendor/css/bootstrap-logsearch.min.css"
-      ],
-      "scripts": [
-        "../node_modules/jquery/dist/jquery.min.js",
-        "../node_modules/bootstrap/dist/js/bootstrap.min.js",
-        "../src/vendor/js/bootstrap-logsearch.min.js"
-      ],
+      "prefix": "",
       "environmentSource": "environments/environment.ts",
       "environments": {
         "dev": "environments/environment.ts",
@@ -36,11 +24,6 @@
       }
     }
   ],
-  "e2e": {
-    "protractor": {
-      "config": "./protractor.conf.js"
-    }
-  },
   "lint": [
     {
       "project": "src/tsconfig.app.json"
@@ -52,13 +35,8 @@
       "project": "e2e/tsconfig.e2e.json"
     }
   ],
-  "test": {
-    "karma": {
-      "config": "./karma.conf.js"
-    }
-  },
   "defaults": {
-    "styleExt": "less",
-    "component": {}
-  }
+    "styleExt": "less"
+  },
+  "packageManager": "yarn"
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2a6dd58f/ambari-logsearch/ambari-logsearch-web/README.md
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/README.md b/ambari-logsearch/ambari-logsearch-web/README.md
index ff1456e..081d22a 100644
--- a/ambari-logsearch/ambari-logsearch-web/README.md
+++ b/ambari-logsearch/ambari-logsearch-web/README.md
@@ -4,7 +4,7 @@ This project was generated with [Angular CLI](https://github.com/angular/angular
 
 ## Development server
 
-Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
+Run `npm start` or `yarn start` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
 
 ## Code scaffolding
 
@@ -12,16 +12,16 @@ Run `ng generate component component-name` to generate a new component. You can
 
 ## Build
 
-Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
+Run `npm run build` or `yarn build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `npm run build-prod` or `yarn build-prod` command for a production build.
 
 ## Running unit tests
 
-Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
+Run `npm test` or `yarn test` to execute the unit tests via [Karma](https://karma-runner.github.io).
 
 ## Running end-to-end tests
 
-Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
-Before running the tests make sure you are serving the app via `ng serve`.
+Run `npm run e2e` or `yarn e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
+Before running the tests make sure you are serving the app via `npm start` or `yarn start`.
 
 ## Further help
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2a6dd58f/ambari-logsearch/ambari-logsearch-web/package.json
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/package.json b/ambari-logsearch/ambari-logsearch-web/package.json
index 0892d85..7e8a0ba 100644
--- a/ambari-logsearch/ambari-logsearch-web/package.json
+++ b/ambari-logsearch/ambari-logsearch-web/package.json
@@ -4,12 +4,13 @@
   "license": "Apache 2.0",
   "scripts": {
     "ng": "ng",
-    "start": "ng serve",
-    "build": "ng build",
-    "build-prod": "ng build -prod",
-    "test": "ng test",
+    "start": "webpack-dev-server --port=4200",
+    "build": "webpack",
+    "build-prod": "NODE_ENV='production' webpack -p",
+    "test": "karma start ./karma.conf.js",
     "lint": "ng lint",
-    "e2e": "ng e2e"
+    "e2e": "protractor ./protractor.conf.js",
+    "pree2e": "webdriver-manager update --standalone false --gecko false --quiet"
   },
   "dependencies": {
     "@angular/common": "^4.0.0",
@@ -60,6 +61,27 @@
     "protractor": "~5.1.0",
     "ts-node": "~2.0.0",
     "tslint": "~4.5.0",
-    "typescript": "~2.2.0"
+    "typescript": "~2.2.0",
+    "webpack-dev-server": "~2.7.1",
+    "webpack": "~3.5.5",
+    "autoprefixer": "^6.5.3",
+    "css-loader": "^0.28.1",
+    "cssnano": "^3.10.0",
+    "exports-loader": "^0.6.3",
+    "file-loader": "^0.10.0",
+    "html-webpack-plugin": "^2.29.0",
+    "less-loader": "^4.0.5",
+    "postcss-loader": "^1.3.3",
+    "postcss-url": "^5.1.2",
+    "raw-loader": "^0.5.1",
+    "sass-loader": "^6.0.3",
+    "source-map-loader": "^0.2.0",
+    "istanbul-instrumenter-loader": "^2.0.0",
+    "style-loader": "^0.13.1",
+    "stylus-loader": "^3.0.1",
+    "url-loader": "^0.5.7",
+    "circular-dependency-plugin": "^3.0.0",
+    "webpack-concat-plugin": "1.4.0",
+    "copy-webpack-plugin": "^4.0.1"
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2a6dd58f/ambari-logsearch/ambari-logsearch-web/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/pom.xml b/ambari-logsearch/ambari-logsearch-web/pom.xml
index 075527b..7a6b02e 100644
--- a/ambari-logsearch/ambari-logsearch-web/pom.xml
+++ b/ambari-logsearch/ambari-logsearch-web/pom.xml
@@ -117,6 +117,7 @@
                     <include>karma.conf.js</include>
                     <include>tsconfig.json</include>
                     <include>tslint.json</include>
+                    <include>webpack.config.js</include>
                   </includes>
                 </resource>
               </resources>

http://git-wip-us.apache.org/repos/asf/ambari/blob/2a6dd58f/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts b/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
index c15ecbc..8ea933c 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
@@ -79,7 +79,7 @@ import {TimeZoneAbbrPipe} from '@app/pipes/timezone-abbr.pipe';
 
 export function HttpLoaderFactory(http: Http) {
   // adding 'static' parameter to step over mock data request
-  return new TranslateHttpLoader(http, 'assets/i18n/', '.json?static=true');
+  return new TranslateHttpLoader(http, 'resources/assets/i18n/', '.json?static=true');
 }
 
 export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSRFStrategy, options: ResponseOptions): any {

http://git-wip-us.apache.org/repos/asf/ambari/blob/2a6dd58f/ambari-logsearch/ambari-logsearch-web/webpack.config.js
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/webpack.config.js b/ambari-logsearch/ambari-logsearch-web/webpack.config.js
new file mode 100644
index 0000000..72eaa7f
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/webpack.config.js
@@ -0,0 +1,530 @@
+/**
+ * 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.
+ */
+
+const fs = require('fs');
+const path = require('path');
+const ConcatPlugin = require('webpack-concat-plugin');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
+const ProgressPlugin = require('webpack/lib/ProgressPlugin');
+const CircularDependencyPlugin = require('circular-dependency-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const autoprefixer = require('autoprefixer');
+const postcssUrl = require('postcss-url');
+const cssnano = require('cssnano');
+
+const {NoEmitOnErrorsPlugin, SourceMapDevToolPlugin, NamedModulesPlugin} = require('webpack');
+const {InsertConcatAssetsWebpackPlugin, NamedLazyChunksWebpackPlugin, BaseHrefWebpackPlugin} = require('@angular/cli/plugins/webpack');
+const {CommonsChunkPlugin} = require('webpack').optimize;
+const {AotPlugin} = require('@ngtools/webpack');
+
+const nodeModules = path.join(process.cwd(), 'node_modules');
+const realNodeModules = fs.realpathSync(nodeModules);
+const genDirNodeModules = path.join(process.cwd(), 'src', '$$_gendir', 'node_modules');
+const entryPoints = ["inline","polyfills","sw-register","styles","vendor","main"];
+const minimizeCss = false;
+const baseHref = "";
+const deployUrl = "";
+const postcssPlugins = function () {
+        // safe settings based on: https://github.com/ben-eb/cssnano/issues/358#issuecomment-283696193
+        const importantCommentRe = /@preserve|@license|[@#]\s*source(?:Mapping)?URL|^!/i;
+        const minimizeOptions = {
+            autoprefixer: false,
+            safe: true,
+            mergeLonghand: false,
+            discardComments: { remove: (comment) => !importantCommentRe.test(comment) }
+        };
+        return [
+            postcssUrl({
+                url: (URL) => {
+                    // Only convert root relative URLs, which CSS-Loader won't process into require().
+                    if (!URL.startsWith('/') || URL.startsWith('//')) {
+                        return URL;
+                    }
+                    if (deployUrl.match(/:\/\//)) {
+                        // If deployUrl contains a scheme, ignore baseHref use deployUrl as is.
+                        return `${deployUrl.replace(/\/$/, '')}${URL}`;
+                    }
+                    else if (baseHref.match(/:\/\//)) {
+                        // If baseHref contains a scheme, include it as is.
+                        return baseHref.replace(/\/$/, '') +
+                            `/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
+                    }
+                    else {
+                        // Join together base-href, deploy-url and the original URL.
+                        // Also dedupe multiple slashes into single ones.
+                        return `/${baseHref}/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
+                    }
+                }
+            }),
+            autoprefixer(),
+        ].concat(minimizeCss ? [cssnano(minimizeOptions)] : []);
+    };
+
+module.exports = {
+  "resolve": {
+    "extensions": [
+      ".ts",
+      ".js"
+    ],
+    "modules": [
+      "./node_modules",
+      "./node_modules"
+    ],
+    "symlinks": true
+  },
+  "resolveLoader": {
+    "modules": [
+      "./node_modules",
+      "./node_modules"
+    ]
+  },
+  "entry": {
+    "main": [
+      "./src/main.ts"
+    ],
+    "polyfills": [
+      "./src/polyfills.ts"
+    ],
+    "styles": [
+      "./src/styles.less",
+      "./node_modules/bootstrap/dist/css/bootstrap.min.css",
+      "./node_modules/font-awesome/css/font-awesome.min.css",
+      "./src/vendor/css/bootstrap-logsearch.min.css"
+    ]
+  },
+  "output": {
+    "path": path.join(process.cwd(), "dist/resources"),
+    "publicPath": "resources/",
+    "filename": "[name].bundle.js",
+    "chunkFilename": "[id].chunk.js"
+  },
+  "module": {
+    "rules": [
+      {
+        "enforce": "pre",
+        "test": /\.js$/,
+        "loader": "source-map-loader",
+        "exclude": [
+          /(\\|\/)node_modules(\\|\/)/
+        ]
+      },
+      {
+        "test": /\.html$/,
+        "loader": "raw-loader"
+      },
+      {
+        "test": /\.(eot|svg|cur)$/,
+        "loader": "file-loader?name=[name].[ext]"
+      },
+      {
+        "test": /\.(jpg|png|webp|gif|otf|ttf|woff|woff2|ani)$/,
+        "loader": "url-loader?name=[name].[ext]&limit=10000"
+      },
+      {
+        "exclude": [
+          path.join(process.cwd(), "src/styles.less"),
+          path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
+          path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
+          path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css")
+        ],
+        "test": /\.css$/,
+        "use": [
+          "exports-loader?module.exports.toString()",
+          {
+            "loader": "css-loader",
+            "options": {
+              "sourceMap": false,
+              "importLoaders": 1
+            }
+          },
+          {
+            "loader": "postcss-loader",
+            "options": {
+              "ident": "postcss",
+              "plugins": postcssPlugins
+            }
+          }
+        ]
+      },
+      {
+        "exclude": [
+          path.join(process.cwd(), "src/styles.less"),
+          path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
+          path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
+          path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css")
+        ],
+        "test": /\.scss$|\.sass$/,
+        "use": [
+          "exports-loader?module.exports.toString()",
+          {
+            "loader": "css-loader",
+            "options": {
+              "sourceMap": false,
+              "importLoaders": 1
+            }
+          },
+          {
+            "loader": "postcss-loader",
+            "options": {
+              "ident": "postcss",
+              "plugins": postcssPlugins
+            }
+          },
+          {
+            "loader": "sass-loader",
+            "options": {
+              "sourceMap": false,
+              "precision": 8,
+              "includePaths": []
+            }
+          }
+        ]
+      },
+      {
+        "exclude": [
+          path.join(process.cwd(), "src/styles.less"),
+          path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
+          path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
+          path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css")
+        ],
+        "test": /\.less$/,
+        "use": [
+          "exports-loader?module.exports.toString()",
+          {
+            "loader": "css-loader",
+            "options": {
+              "sourceMap": false,
+              "importLoaders": 1
+            }
+          },
+          {
+            "loader": "postcss-loader",
+            "options": {
+              "ident": "postcss",
+              "plugins": postcssPlugins
+            }
+          },
+          {
+            "loader": "less-loader",
+            "options": {
+              "sourceMap": false,
+              "paths": []
+            }
+          }
+        ]
+      },
+      {
+        "exclude": [
+          path.join(process.cwd(), "src/styles.less"),
+          path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
+          path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
+          path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css")
+        ],
+        "test": /\.styl$/,
+        "use": [
+          "exports-loader?module.exports.toString()",
+          {
+            "loader": "css-loader",
+            "options": {
+              "sourceMap": false,
+              "importLoaders": 1
+            }
+          },
+          {
+            "loader": "postcss-loader",
+            "options": {
+              "ident": "postcss",
+              "plugins": postcssPlugins
+            }
+          },
+          {
+            "loader": "stylus-loader",
+            "options": {
+              "sourceMap": false,
+              "paths": []
+            }
+          }
+        ]
+      },
+      {
+        "include": [
+          path.join(process.cwd(), "src/styles.less"),
+          path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
+          path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
+          path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css")
+        ],
+        "test": /\.css$/,
+        "use": [
+          "style-loader",
+          {
+            "loader": "css-loader",
+            "options": {
+              "sourceMap": false,
+              "importLoaders": 1
+            }
+          },
+          {
+            "loader": "postcss-loader",
+            "options": {
+              "ident": "postcss",
+              "plugins": postcssPlugins
+            }
+          }
+        ]
+      },
+      {
+        "include": [
+          path.join(process.cwd(), "src/styles.less"),
+          path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
+          path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
+          path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css")
+        ],
+        "test": /\.scss$|\.sass$/,
+        "use": [
+          "style-loader",
+          {
+            "loader": "css-loader",
+            "options": {
+              "sourceMap": false,
+              "importLoaders": 1
+            }
+          },
+          {
+            "loader": "postcss-loader",
+            "options": {
+              "ident": "postcss",
+              "plugins": postcssPlugins
+            }
+          },
+          {
+            "loader": "sass-loader",
+            "options": {
+              "sourceMap": false,
+              "precision": 8,
+              "includePaths": []
+            }
+          }
+        ]
+      },
+      {
+        "include": [
+          path.join(process.cwd(), "src/styles.less"),
+          path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
+          path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
+          path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css")
+        ],
+        "test": /\.less$/,
+        "use": [
+          "style-loader",
+          {
+            "loader": "css-loader",
+            "options": {
+              "sourceMap": false,
+              "importLoaders": 1
+            }
+          },
+          {
+            "loader": "postcss-loader",
+            "options": {
+              "ident": "postcss",
+              "plugins": postcssPlugins
+            }
+          },
+          {
+            "loader": "less-loader",
+            "options": {
+              "sourceMap": false,
+              "paths": []
+            }
+          }
+        ]
+      },
+      {
+        "include": [
+          path.join(process.cwd(), "src/styles.less"),
+          path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
+          path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
+          path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css")
+        ],
+        "test": /\.styl$/,
+        "use": [
+          "style-loader",
+          {
+            "loader": "css-loader",
+            "options": {
+              "sourceMap": false,
+              "importLoaders": 1
+            }
+          },
+          {
+            "loader": "postcss-loader",
+            "options": {
+              "ident": "postcss",
+              "plugins": postcssPlugins
+            }
+          },
+          {
+            "loader": "stylus-loader",
+            "options": {
+              "sourceMap": false,
+              "paths": []
+            }
+          }
+        ]
+      },
+      {
+        "test": /\.ts$/,
+        "loader": "@ngtools/webpack"
+      }
+    ]
+  },
+  "plugins": [
+    new NoEmitOnErrorsPlugin(),
+    new ConcatPlugin({
+      "uglify": false,
+      "sourceMap": true,
+      "name": "scripts",
+      "fileName": "../resources/[name].bundle.js",
+      "filesToConcat": [
+        "node_modules/jquery/dist/jquery.min.js",
+        "node_modules/bootstrap/dist/js/bootstrap.min.js",
+        "src/vendor/js/bootstrap-logsearch.min.js"
+      ]
+    }),
+    new InsertConcatAssetsWebpackPlugin([
+      "scripts"
+    ]),
+    new CopyWebpackPlugin([
+      {
+        "context": "src/",
+        "to": "",
+        "from": {
+          "glob": "assets/**/*",
+          "dot": true
+        }
+      },
+      {
+        "context": "src/",
+        "to": "../favicon.ico",
+        "from": {
+          "glob": "favicon.ico",
+          "dot": true
+        }
+      }
+    ], {
+      "ignore": [
+        ".gitkeep"
+      ],
+      "debug": "warning"
+    }),
+    new ProgressPlugin(),
+    new CircularDependencyPlugin({
+      "exclude": /(\\|\/)node_modules(\\|\/)/,
+      "failOnError": false
+    }),
+    new NamedLazyChunksWebpackPlugin(),
+    new HtmlWebpackPlugin({
+      "template": "./src/index.html",
+      "filename": "../index.html",
+      "hash": false,
+      "inject": true,
+      "compile": true,
+      "favicon": false,
+      "minify": false,
+      "cache": true,
+      "showErrors": true,
+      "chunks": "all",
+      "excludeChunks": [],
+      "title": "Webpack App",
+      "xhtml": true,
+      "chunksSortMode": function sort(left, right) {
+        let leftIndex = entryPoints.indexOf(left.names[0]);
+        let rightindex = entryPoints.indexOf(right.names[0]);
+        if (leftIndex > rightindex) {
+            return 1;
+        }
+        else if (leftIndex < rightindex) {
+            return -1;
+        }
+        else {
+            return 0;
+        }
+    }
+    }),
+    new BaseHrefWebpackPlugin({}),
+    new CommonsChunkPlugin({
+      "name": [
+        "inline"
+      ],
+      "minChunks": null
+    }),
+    new CommonsChunkPlugin({
+      "name": [
+        "vendor"
+      ],
+      "minChunks": (module) => {
+                return module.resource
+                    && (module.resource.startsWith(nodeModules)
+                        || module.resource.startsWith(genDirNodeModules)
+                        || module.resource.startsWith(realNodeModules));
+            },
+      "chunks": [
+        "main"
+      ]
+    }),
+    new SourceMapDevToolPlugin({
+      "filename": "[file].map[query]",
+      "moduleFilenameTemplate": "[resource-path]",
+      "fallbackModuleFilenameTemplate": "[resource-path]?[hash]",
+      "sourceRoot": "webpack:///"
+    }),
+    new CommonsChunkPlugin({
+      "name": [
+        "main"
+      ],
+      "minChunks": 2,
+      "async": "common"
+    }),
+    new NamedModulesPlugin({}),
+    new AotPlugin({
+      "mainPath": "main.ts",
+      "replaceExport": false,
+      "hostReplacementPaths": {
+        "environments/environment.ts": `environments/environment${process.env.NODE_ENV === "production" ? ".prod" : ""}.ts`
+      },
+      "exclude": [],
+      "tsConfigPath": "src/tsconfig.app.json",
+      "skipCodeGeneration": true
+    })
+  ],
+  "node": {
+    "fs": "empty",
+    "global": true,
+    "crypto": "empty",
+    "tls": "empty",
+    "net": "empty",
+    "process": true,
+    "module": false,
+    "clearImmediate": false,
+    "setImmediate": false
+  },
+  "devServer": {
+    "contentBase": path.join(process.cwd(), "dist"),
+    "historyApiFallback": true
+  }
+};


[27/38] ambari git commit: AMBARI-21545 Stack Advisor support for LDAP configuration (benyoka)

Posted by lp...@apache.org.
AMBARI-21545 Stack Advisor support for LDAP configuration (benyoka)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/a7757b22
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/a7757b22
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/a7757b22

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: a7757b222d33b7aace9319303956c6bf456cb16c
Parents: faf9534
Author: Balazs Bence Sari <be...@apache.org>
Authored: Tue Aug 8 20:17:14 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:30 2017 +0200

----------------------------------------------------------------------
 .../services/AmbariConfigurationService.java    |   4 +-
 .../stackadvisor/StackAdvisorRequest.java       |  12 ++
 .../commands/StackAdvisorCommand.java           |  54 +++++
 .../commands/StackAdvisorCommandTest.java       | 212 +++++++++++++++++++
 .../StackAdvisorResourceProviderTest.java       |  97 ++++-----
 5 files changed, 324 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/a7757b22/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
index 0632361..927e518 100644
--- 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
@@ -56,9 +56,9 @@ import io.swagger.annotations.ApiResponses;
  *            "data": [
  *                {
  *                 "authentication.ldap.primaryUrl": "localhost:33389"
-                   "authentication.ldap.secondaryUrl": "localhost:333"
+ *                 "authentication.ldap.secondaryUrl": "localhost:333"
  *                 "authentication.ldap.baseDn": "dc=ambari,dc=apache,dc=org"
-  *                 // ......
+ *                 // ......
  *         ]
  *     }
  * </pre>

http://git-wip-us.apache.org/repos/asf/ambari/blob/a7757b22/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
index 3a2b488..cd26c56 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
@@ -31,6 +31,8 @@ import org.apache.ambari.server.api.services.stackadvisor.recommendations.Recomm
 import org.apache.ambari.server.state.ChangedConfigInfo;
 import org.apache.commons.lang.StringUtils;
 
+import com.google.common.base.Preconditions;
+
 /**
  * Stack advisor request.
  */
@@ -48,6 +50,7 @@ public class StackAdvisorRequest {
   private List<ChangedConfigInfo> changedConfigurations = new LinkedList<>();
   private Set<RecommendationResponse.ConfigGroup> configGroups;
   private Map<String, String> userContext = new HashMap<>();
+  private Map<String, Object> ldapConfig = new HashMap<>();
 
   public String getStackName() {
     return stackName;
@@ -93,6 +96,8 @@ public class StackAdvisorRequest {
     return configurations;
   }
 
+  public Map<String, Object> getLdapConfig() { return ldapConfig; }
+
   public List<ChangedConfigInfo> getChangedConfigurations() {
     return changedConfigurations;
   }
@@ -189,6 +194,13 @@ public class StackAdvisorRequest {
       return this;
     }
 
+    public StackAdvisorRequestBuilder withLdapConfig(Map<String, Object> ldapConfig) {
+      Preconditions.checkNotNull(ldapConfig);
+      this.instance.ldapConfig = ldapConfig;
+      return this;
+    }
+
+
     public StackAdvisorRequest build() {
       return this.instance;
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a7757b22/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
index 356754d..2dc45de 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
@@ -84,6 +84,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
       + ",services/configurations/dependencies/StackConfigurationDependency/dependency_name"
       + ",services/configurations/dependencies/StackConfigurationDependency/dependency_type,services/configurations/StackConfigurations/type"
       + "&services/StackServices/service_name.in(%s)";
+  private static final String GET_LDAP_CONFIG_URI = "/api/v1/configurations?AmbariConfiguration/type=ldap&fields=AmbariConfiguration/*";
   private static final String SERVICES_PROPERTY = "services";
   private static final String SERVICES_COMPONENTS_PROPERTY = "components";
   private static final String CONFIG_GROUPS_PROPERTY = "config-groups";
@@ -95,6 +96,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
   private static final String CHANGED_CONFIGURATIONS_PROPERTY = "changed-configurations";
   private static final String USER_CONTEXT_PROPERTY = "user-context";
   private static final String AMBARI_SERVER_CONFIGURATIONS_PROPERTY = "ambari-server-properties";
+  protected static final String LDAP_CONFIGURATION_PROPERTY = "ldap-configuration";
 
   private File recommendationsDir;
   private String recommendationsArtifactsLifetime;
@@ -160,6 +162,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
       populateConfigurations(root, request);
       populateConfigGroups(root, request);
       populateAmbariServerInfo(root);
+      populateLdapConfiguration(root);
       data.servicesJSON = mapper.writeValueAsString(root);
     } catch (Exception e) {
       // should not happen
@@ -171,6 +174,52 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
     return data;
   }
 
+  /**
+   * Retrieves the LDAP configuration if exists and adds it to services.json
+   * @param root The JSON document that will become service.json when passed to the stack advisor engine
+   * @throws StackAdvisorException
+   * @throws IOException
+   */
+  protected void populateLdapConfiguration(ObjectNode root) throws StackAdvisorException, IOException {
+    Response response = handleRequest(null, null, new LocalUriInfo(GET_LDAP_CONFIG_URI), Request.Type.GET,
+        createConfigResource());
+
+    if (response.getStatus() != Status.OK.getStatusCode()) {
+      String message = String.format(
+          "Error occured during retrieving ldap configuration, status=%s, response=%s",
+          response.getStatus(), (String) response.getEntity());
+      LOG.warn(message);
+      throw new StackAdvisorException(message);
+    }
+
+    String ldapConfigJSON = (String) response.getEntity();
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("LDAP configuration: {}", ldapConfigJSON);
+    }
+
+    JsonNode ldapConfigRoot = mapper.readTree(ldapConfigJSON);
+    ArrayNode ldapConfigs = ((ArrayNode)ldapConfigRoot.get("items"));
+    int numConfigs = ldapConfigs.size();
+    // Zero or one config may exist
+    switch (numConfigs) {
+      case 0:
+        LOG.debug("No LDAP config is stored in the DB");
+        break;
+      case 1:
+        ArrayNode ldapConfigData = (ArrayNode)ldapConfigs.get(0).get("AmbariConfiguration").get("data");
+        if (ldapConfigData.size() == 0) {
+          throw new StackAdvisorException("No configuration data for LDAP configuration.");
+        }
+        if (ldapConfigData.size() > 1) {
+          throw new StackAdvisorException("Ambigous configuration data for LDAP configuration.");
+        }
+        root.put(LDAP_CONFIGURATION_PROPERTY, ldapConfigData.get(0));
+        break;
+      default:
+        throw new StackAdvisorException(String.format("Multiple (%s) LDAP configs are found in the DB.", numConfigs));
+    }
+  }
+
   protected void populateAmbariServerInfo(ObjectNode root) throws StackAdvisorException {
     Map<String, String> serverProperties = metaInfo.getAmbariServerProperties();
 
@@ -437,6 +486,11 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
     return createResource(Resource.Type.Host, mapIds);
   }
 
+  protected ResourceInstance createConfigResource() {
+    return createResource(Resource.Type.AmbariConfiguration, new HashMap<>());
+  }
+
+
   private ResourceInstance createStackVersionResource(String stackName, String stackVersion) {
     Map<Resource.Type, String> mapIds = new HashMap<>();
     mapIds.put(Resource.Type.Stack, stackName);

http://git-wip-us.apache.org/repos/asf/ambari/blob/a7757b22/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
index eaa4716..959db15 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.api.services.stackadvisor.commands;
 
+import static org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommand.LDAP_CONFIGURATION_PROPERTY;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -33,12 +34,21 @@ import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 import javax.ws.rs.WebApplicationException;
+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.api.resources.ResourceInstance;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.api.services.ResultStatus;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest.StackAdvisorRequestBuilder;
@@ -50,6 +60,7 @@ import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.commons.io.FileUtils;
 import org.codehaus.jackson.JsonNode;
 import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.node.ArrayNode;
 import org.codehaus.jackson.node.ObjectNode;
 import org.junit.After;
@@ -59,6 +70,8 @@ import org.junit.rules.TemporaryFolder;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
+import com.google.common.collect.Lists;
+
 /**
  * StackAdvisorCommand unit tests.
  */
@@ -265,6 +278,197 @@ public class StackAdvisorCommandTest {
     assertEquals(0, stackVersions.size());
   }
 
+  @Test
+  public void testPopulateLdapConfig() throws Exception {
+    File recommendationsDir = temp.newFolder("recommendationDir");
+    String recommendationsArtifactsLifetime = "1w";
+    int requestId = 0;
+    StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
+    AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    doReturn(Collections.emptyList()).when(metaInfo).getStackParentVersions(anyString(), anyString());
+    TestStackAdvisorCommand command = spy(new TestStackAdvisorCommand(recommendationsDir, recommendationsArtifactsLifetime,
+      ServiceInfo.ServiceAdvisorType.PYTHON, requestId, saRunner, metaInfo));
+
+    StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion").build();
+
+    Map<String, Object> ldapConfigData = map(
+      "authentication.ldap.primaryUrl", "localhost:33389",
+      "authentication.ldap.secondaryUrl", "localhost:333",
+      "authentication.ldap.baseDn", "c=ambari,dc=apache,dc=org"
+    );
+
+    Map<String, Object> storedLdapConfigResult =  map(
+      "items",
+      list(
+        map(
+          "AmbariConfiguration",
+          map(
+            "data", list(ldapConfigData)
+          )
+        )
+      )
+    );
+
+    Response response =
+      Response.status(ResultStatus.STATUS.OK.getStatus()).entity(jsonString(storedLdapConfigResult)).build();
+
+    doReturn(response).when(command).handleRequest(any(), any(), any(), any(), any(), any());
+
+    JsonNode servicesRootNode = json("{}");
+    command.populateLdapConfiguration((ObjectNode)servicesRootNode);
+
+    JsonNode expectedLdapConfig = json(
+      map(LDAP_CONFIGURATION_PROPERTY, ldapConfigData)
+    );
+
+    assertEquals(expectedLdapConfig, servicesRootNode);
+  }
+
+  @Test
+  public void testPopulateLdapConfig_NoConfigs() throws Exception {
+    File recommendationsDir = temp.newFolder("recommendationDir");
+    String recommendationsArtifactsLifetime = "1w";
+    int requestId = 0;
+    StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
+    AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    doReturn(Collections.emptyList()).when(metaInfo).getStackParentVersions(anyString(), anyString());
+    TestStackAdvisorCommand command = spy(new TestStackAdvisorCommand(recommendationsDir, recommendationsArtifactsLifetime,
+      ServiceInfo.ServiceAdvisorType.PYTHON, requestId, saRunner, metaInfo));
+
+    StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion").build();
+
+    Map<String, Object> storedLdapConfigResult =  map(
+      "items", list()
+    );
+
+    Response response =
+      Response.status(ResultStatus.STATUS.OK.getStatus()).entity(jsonString(storedLdapConfigResult)).build();
+
+    doReturn(response).when(command).handleRequest(any(), any(), any(), any(), any(), any());
+
+    JsonNode servicesRootNode = json("{}");
+    command.populateLdapConfiguration((ObjectNode)servicesRootNode);
+
+    JsonNode expectedLdapConfig = json("{}");
+
+    assertEquals(expectedLdapConfig, servicesRootNode);
+  }
+
+  /**
+   * An ambigous ldap config that has two items in its data[] array should result in exception
+   */
+  @Test(expected = StackAdvisorException.class)
+  public void testPopulateLdapConfig_multipleConfigs() throws Exception {
+    File recommendationsDir = temp.newFolder("recommendationDir");
+    String recommendationsArtifactsLifetime = "1w";
+    int requestId = 0;
+    StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
+    AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    doReturn(Collections.emptyList()).when(metaInfo).getStackParentVersions(anyString(), anyString());
+    TestStackAdvisorCommand command = spy(new TestStackAdvisorCommand(recommendationsDir, recommendationsArtifactsLifetime,
+        ServiceInfo.ServiceAdvisorType.PYTHON, requestId, saRunner, metaInfo));
+
+    StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion").build();
+
+    Map<String, Object> ldapConfigData = map(
+      "authentication.ldap.primaryUrl", "localhost:33389",
+      "authentication.ldap.secondaryUrl", "localhost:333",
+      "authentication.ldap.baseDn", "c=ambari,dc=apache,dc=org"
+    );
+
+    Map<String, Object> storedLdapConfigResult =  map(
+      "items",
+      list(
+        map(
+          "AmbariConfiguration",
+          map(
+            "data",
+            list(ldapConfigData, ldapConfigData)
+          )
+        )
+      )
+    );
+
+    Response response =
+     Response.status(ResultStatus.STATUS.OK.getStatus()).entity(jsonString(storedLdapConfigResult)).build();
+
+    doReturn(response).when(command).handleRequest(any(), any(), any(), any(), any(), any());
+
+    JsonNode servicesRootNode = json("{}");
+    command.populateLdapConfiguration((ObjectNode)servicesRootNode);
+  }
+
+  /**
+   * An if multiple ambari configurations are stored with 'ldap-config' type, an
+   * exception should be thrown
+   */
+  @Test(expected = StackAdvisorException.class)
+  public void testPopulateLdapConfig_multipleResults() throws Exception {
+    File recommendationsDir = temp.newFolder("recommendationDir");
+    String recommendationsArtifactsLifetime = "1w";
+    int requestId = 0;
+    StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
+    AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    doReturn(Collections.emptyList()).when(metaInfo).getStackParentVersions(anyString(), anyString());
+    TestStackAdvisorCommand command = spy(new TestStackAdvisorCommand(recommendationsDir, recommendationsArtifactsLifetime,
+      ServiceInfo.ServiceAdvisorType.PYTHON, requestId, saRunner, metaInfo));
+
+    StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
+      .build();
+
+    Map<String, Object> ldapConfig = map(
+      "AmbariConfiguration",
+      map(
+        "data",
+        list(
+          map(
+            "authentication.ldap.primaryUrl", "localhost:33389",
+            "authentication.ldap.secondaryUrl", "localhost:333",
+            "authentication.ldap.baseDn", "c=ambari,dc=apache,dc=org"
+          )
+        )
+      )
+    );
+
+    Map<String, Object> storedLdapConfigResult = map(
+      "items",
+      list(ldapConfig, ldapConfig)
+    );
+
+    Response response =
+      Response.status(ResultStatus.STATUS.OK.getStatus()).entity(jsonString(storedLdapConfigResult)).build();
+
+    doReturn(response).when(command).handleRequest(any(), any(), any(), any(), any(), any());
+
+    JsonNode servicesRootNode = json("{}");
+    command.populateLdapConfiguration((ObjectNode)servicesRootNode);
+  }
+
+  private static String jsonString(Object obj) throws IOException {
+    return new ObjectMapper().writeValueAsString(obj);
+  }
+
+  private static JsonNode json(Object obj) throws IOException {
+    return new ObjectMapper().convertValue(obj, JsonNode.class);
+  }
+
+  private static JsonNode json(String jsonString) throws IOException {
+    return new ObjectMapper().readTree(jsonString);
+  }
+
+  private static List<Object> list(Object... items) {
+    return Lists.newArrayList(items);
+  }
+
+  private static Map<String, Object> map(Object... keysAndValues) {
+    Map<String, Object> map = new HashMap<>();
+    Iterator<Object> iterator = Arrays.asList(keysAndValues).iterator();
+    while (iterator.hasNext()) {
+      map.put(iterator.next().toString(), iterator.next());
+    }
+    return map;
+  }
+
   class TestStackAdvisorCommand extends StackAdvisorCommand<TestResource> {
     public TestStackAdvisorCommand(File recommendationsDir, String recommendationsArtifactsLifetime, ServiceInfo.ServiceAdvisorType serviceAdvisorType,
                                    int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
@@ -290,6 +494,14 @@ public class StackAdvisorCommandTest {
     protected TestResource updateResponse(StackAdvisorRequest request, TestResource response) {
       return response;
     }
+
+    // Overridden to ensure visiblity in tests
+    @Override
+    public javax.ws.rs.core.Response handleRequest(HttpHeaders headers, String body,
+                                                                  UriInfo uriInfo, Request.Type requestType,
+                                                                  MediaType mediaType, ResourceInstance resource) {
+      return super.handleRequest(headers, body, uriInfo, requestType, mediaType, resource);
+    }
   }
 
   public static class TestResource extends StackAdvisorResponse {

http://git-wip-us.apache.org/repos/asf/ambari/blob/a7757b22/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProviderTest.java
index ab60948..05232ea 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProviderTest.java
@@ -27,43 +27,35 @@ import static org.junit.Assert.assertNotNull;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.Nonnull;
+
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.spi.Request;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
+import com.google.common.collect.Lists;
+
 public class StackAdvisorResourceProviderTest {
 
+  private RecommendationResourceProvider provider;
+
   @Test
   public void testCalculateConfigurations() throws Exception {
-
-    Map<Resource.Type, String> keyPropertyIds = Collections.emptyMap();
-    Set<String> propertyIds = Collections.emptySet();
-    AmbariManagementController ambariManagementController = mock(AmbariManagementController.class);
-    RecommendationResourceProvider provider = new RecommendationResourceProvider(propertyIds,
-        keyPropertyIds, ambariManagementController);
-
-    Request request = mock(Request.class);
-    Set<Map<String, Object>> propertiesSet = new HashSet<>();
-    Map<String, Object> propertiesMap = new HashMap<>();
-    propertiesMap.put(CONFIGURATIONS_PROPERTY_ID + "site/properties/string_prop", "string");
-    List<Object> array = new ArrayList<>();
-    array.add("array1");
-    array.add("array2");
-    propertiesMap.put(CONFIGURATIONS_PROPERTY_ID + "site/properties/array_prop", array);
-    propertiesSet.add(propertiesMap);
-
-    doReturn(propertiesSet).when(request).getProperties();
+    Request request = createMockRequest(
+        CONFIGURATIONS_PROPERTY_ID + "site/properties/string_prop", "string",
+        CONFIGURATIONS_PROPERTY_ID + "site/properties/array_prop", Lists.newArrayList("array1", "array2"));
 
     Map<String, Map<String, Map<String, String>>> calculatedConfigurations = provider.calculateConfigurations(request);
 
@@ -79,27 +71,37 @@ public class StackAdvisorResourceProviderTest {
     assertEquals("[array1, array2]", properties.get("array_prop"));
   }
 
-  @Test
-  public void testReadUserContext() throws Exception {
-
+  @Nonnull
+  private RecommendationResourceProvider createRecommendationResourceProvider() {
     Map<Resource.Type, String> keyPropertyIds = Collections.emptyMap();
     Set<String> propertyIds = Collections.emptySet();
     AmbariManagementController ambariManagementController = mock(AmbariManagementController.class);
-    RecommendationResourceProvider provider = new RecommendationResourceProvider(propertyIds,
-                                                                                 keyPropertyIds, ambariManagementController);
+    return new RecommendationResourceProvider(propertyIds,
+        keyPropertyIds, ambariManagementController);
+  }
 
+  @Nonnull
+  private Request createMockRequest(Object... propertyKeysAndValues) {
     Request request = mock(Request.class);
     Set<Map<String, Object>> propertiesSet = new HashSet<>();
     Map<String, Object> propertiesMap = new HashMap<>();
-    propertiesMap.put(CONFIGURATIONS_PROPERTY_ID + "site/properties/string_prop", "string");
-    List<Object> array = new ArrayList<>();
-    array.add("array1");
-    array.add("array2");
-    propertiesMap.put(USER_CONTEXT_OPERATION_PROPERTY, "op1");
-    propertiesMap.put(USER_CONTEXT_OPERATION_DETAILS_PROPERTY, "op_det");
+    Iterator<Object> it = Arrays.asList(propertyKeysAndValues).iterator();
+    while(it.hasNext()) {
+      String key = (String)it.next();
+      Object value = it.next();
+      propertiesMap.put(key, value);
+    }
     propertiesSet.add(propertiesMap);
-
     doReturn(propertiesSet).when(request).getProperties();
+    return request;
+  }
+
+  @Test
+  public void testReadUserContext() throws Exception {
+    Request request = createMockRequest(
+        CONFIGURATIONS_PROPERTY_ID + "site/properties/string_prop", "string",
+        USER_CONTEXT_OPERATION_PROPERTY, "op1",
+        USER_CONTEXT_OPERATION_DETAILS_PROPERTY, "op_det");
 
     Map<String, String> userContext = provider.readUserContext(request);
 
@@ -111,24 +113,9 @@ public class StackAdvisorResourceProviderTest {
 
   @Test
   public void testCalculateConfigurationsWithNullPropertyValues() throws Exception {
-
-    Map<Resource.Type, String> keyPropertyIds = Collections.emptyMap();
-    Set<String> propertyIds = Collections.emptySet();
-    AmbariManagementController ambariManagementController = mock(AmbariManagementController.class);
-    RecommendationResourceProvider provider = new RecommendationResourceProvider(propertyIds,
-      keyPropertyIds, ambariManagementController);
-
-    Request request = mock(Request.class);
-    Set<Map<String, Object>> propertiesSet = new HashSet<>();
-    Map<String, Object> propertiesMap = new HashMap<>();
-    propertiesMap.put(CONFIGURATIONS_PROPERTY_ID + "site/properties/string_prop", null); //null value means no value specified for the property
-    List<Object> array = new ArrayList<>();
-    array.add("array1");
-    array.add("array2");
-    propertiesMap.put(CONFIGURATIONS_PROPERTY_ID + "site/properties/array_prop", array);
-    propertiesSet.add(propertiesMap);
-
-    doReturn(propertiesSet).when(request).getProperties();
+    Request request = createMockRequest(
+        CONFIGURATIONS_PROPERTY_ID + "site/properties/string_prop", null,
+        CONFIGURATIONS_PROPERTY_ID + "site/properties/array_prop", Lists.newArrayList("array1", "array2"));
 
     Map<String, Map<String, Map<String, String>>> calculatedConfigurations = provider.calculateConfigurations(request);
 
@@ -142,19 +129,18 @@ public class StackAdvisorResourceProviderTest {
 
     assertEquals("[array1, array2]", properties.get("array_prop"));
 
-
     // config properties with null values should be ignored
     assertFalse(properties.containsKey("string_prop"));
-
   }
 
+ 
   @Test
   public void testStackAdvisorWithEmptyHosts() {
     Map<Resource.Type, String> keyPropertyIds = Collections.emptyMap();
     Set<String> propertyIds = Collections.emptySet();
     AmbariManagementController ambariManagementController = mock(AmbariManagementController.class);
     RecommendationResourceProvider provider = new RecommendationResourceProvider(propertyIds,
-      keyPropertyIds, ambariManagementController);
+            keyPropertyIds, ambariManagementController);
 
     Request request = mock(Request.class);
     Set<Map<String, Object>> propertiesSet = new HashSet<>();
@@ -170,4 +156,9 @@ public class StackAdvisorResourceProviderTest {
     } catch (Exception e) {
     }
   }
+
+  @Before
+  public void init() {
+    provider = createRecommendationResourceProvider();
+  }
 }


[28/38] ambari git commit: AMBARI-21307 Draft skimplementation for the user related ldap config attribute validation

Posted by lp...@apache.org.
AMBARI-21307 Draft skimplementation for the user related ldap config attribute validation


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/43dbbc95
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/43dbbc95
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/43dbbc95

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 43dbbc9594cc9fbd61a1152556d8c896ef21ca76
Parents: 642b578
Author: lpuskas <lp...@apache.org>
Authored: Tue Jul 18 17:48:07 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:30 2017 +0200

----------------------------------------------------------------------
 ambari-project/pom.xml                          |   1 +
 ambari-server/pom.xml                           |   7 +-
 .../AmbariConfigurationRequestSwagger.java      |   1 -
 .../services/ldap/AmbariConfigurationDTO.java   |  67 +++++++
 .../ldap/LdapCheckConfigurationRequest.java     |  47 +++++
 .../api/services/ldap/LdapOperationRequest.java |  18 ++
 .../api/services/ldap/LdapRequestInfo.java      |  61 +++++++
 .../api/services/ldap/LdapRestService.java      | 132 ++++++++++++++
 .../ambari/server/controller/AmbariServer.java  |   3 +-
 .../server/controller/ControllerModule.java     |   1 +
 .../server/ldap/AmbariLdapConfiguration.java    | 129 ++++++++++++++
 .../server/ldap/LdapConfigurationFactory.java   |  21 +++
 .../ldap/LdapConfigurationValidatorService.java |  52 ++++++
 .../apache/ambari/server/ldap/LdapModule.java   |  37 ++++
 .../ldap/service/AmbariLdapException.java       |  33 ++++
 .../server/ldap/service/AmbariLdapFacade.java   | 107 +++++++++++
 .../ambari/server/ldap/service/LdapFacade.java  |  52 ++++++
 .../server/ldap/service/LdapSearchService.java  |  18 ++
 .../ad/AdLdapConfigurationValidatorService.java | 177 +++++++++++++++++++
 .../service/ad/LdapConfigurationConverter.java  |  50 ++++++
 .../api/services/ldap/LDAPServiceTest.java      |  85 +++++++++
 ...AdLdapConfigurationValidatorServiceTest.java | 129 ++++++++++++++
 22 files changed, 1224 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-project/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-project/pom.xml b/ambari-project/pom.xml
index 00ba1bc..e4d4423 100644
--- a/ambari-project/pom.xml
+++ b/ambari-project/pom.xml
@@ -31,6 +31,7 @@
     <ambari.dir>${project.parent.basedir}</ambari.dir>
     <powermock.version>1.6.3</powermock.version>
     <jetty.version>8.1.19.v20160209</jetty.version>
+    <ldap-api.version>1.0.0</ldap-api.version>
     <checkstyle.version>6.19</checkstyle.version> <!-- last version that does not require Java 8 -->
     <swagger.version>1.5.10</swagger.version>
     <swagger.maven.plugin.version>3.1.4</swagger.maven.plugin.version>

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index 29a820a..c0f30be 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -1287,7 +1287,6 @@
     <dependency>
       <groupId>org.apache.directory.shared</groupId>
       <artifactId>shared-ldap</artifactId>
-      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
@@ -1686,8 +1685,12 @@
       <artifactId>jna</artifactId>
       <version>4.2.2</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.directory.api</groupId>
+      <artifactId>api-all</artifactId>
+      <version>${ldap-api.version}</version>
+    </dependency>
   </dependencies>
-
   <pluginRepositories>
     <pluginRepository>
       <id>oss.sonatype.org</id>

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
index d6714f9..5e8094e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
@@ -16,7 +16,6 @@ package org.apache.ambari.server.api.services;
 import java.util.Map;
 
 import org.apache.ambari.server.controller.ApiModel;
-import org.apache.ambari.server.orm.entities.ConfigurationBaseEntity;
 
 import io.swagger.annotations.ApiModelProperty;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java
new file mode 100644
index 0000000..1b134fe
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java
@@ -0,0 +1,67 @@
+/*
+ * 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.ldap;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+public class AmbariConfigurationDTO {
+  private String type;
+  private Set<Map<String, Object>> data = Collections.emptySet();
+  private String versionTag;
+  private Integer version;
+  private long createdTs;
+
+  public String getType() {
+    return type;
+  }
+
+  public void setType(String type) {
+    this.type = type;
+  }
+
+  public Set<Map<String, Object>> getData() {
+    return data;
+  }
+
+  public void setData(Set<Map<String, Object>> data) {
+    this.data = data;
+  }
+
+  public String getVersionTag() {
+    return versionTag;
+  }
+
+  public void setVersionTag(String versionTag) {
+    this.versionTag = versionTag;
+  }
+
+  public Integer getVersion() {
+    return version;
+  }
+
+  public void setVersion(Integer version) {
+    this.version = version;
+  }
+
+  public long getCreatedTs() {
+    return createdTs;
+  }
+
+  public void setCreatedTs(long createdTs) {
+    this.createdTs = createdTs;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java
new file mode 100644
index 0000000..188f1b9
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.ldap;
+
+
+import com.google.gson.annotations.SerializedName;
+
+public class LdapCheckConfigurationRequest implements LdapOperationRequest {
+
+  @SerializedName("AmbariConfiguration")
+  private AmbariConfigurationDTO ambariConfiguration;
+
+  @SerializedName("RequestInfo")
+  private LdapRequestInfo requestInfo;
+
+  public LdapCheckConfigurationRequest() {
+  }
+
+
+  public AmbariConfigurationDTO getAmbariConfiguration() {
+    return ambariConfiguration;
+  }
+
+  public void setAmbariConfiguration(AmbariConfigurationDTO ambariConfiguration) {
+    this.ambariConfiguration = ambariConfiguration;
+  }
+
+  public LdapRequestInfo getRequestInfo() {
+    return requestInfo;
+  }
+
+  public void setRequestInfo(LdapRequestInfo requestInfo) {
+    this.requestInfo = requestInfo;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java
new file mode 100644
index 0000000..06f6c40
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java
@@ -0,0 +1,18 @@
+/*
+ * 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.ldap;
+
+public interface LdapOperationRequest {
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
new file mode 100644
index 0000000..eeecfee
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
@@ -0,0 +1,61 @@
+/*
+ * 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.ldap;
+
+import java.util.Map;
+
+import org.apache.ambari.server.controller.RequestPostRequest;
+
+/**
+ * Bean holding LDAP request specific request information.
+ */
+public class LdapRequestInfo implements RequestPostRequest.RequestInfo {
+
+  // no-arg costructor facilitating JSON serialization
+  public LdapRequestInfo() {
+  }
+
+  private String action;
+
+  private Map<String, Object> parameters;
+
+  @Override
+  public String getAction() {
+    return action;
+  }
+
+  public void setAction(String action) {
+    this.action = action;
+  }
+
+  public void setParameters(Map<String, Object> parameters) {
+    this.parameters = parameters;
+  }
+
+  @Override
+  public String getCommand() {
+    return null;
+  }
+
+  @Override
+  public RequestPostRequest.OperationLevel getOperationLevel() {
+    return null;
+  }
+
+  @Override
+  public Map<String, Object> getParameters() {
+    return parameters;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
new file mode 100644
index 0000000..33b10fa
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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.ldap;
+
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.ambari.annotations.ApiIgnore;
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.api.services.BaseService;
+import org.apache.ambari.server.api.services.Result;
+import org.apache.ambari.server.api.services.ResultImpl;
+import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationFactory;
+import org.apache.ambari.server.ldap.service.LdapFacade;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Endpoint designated to LDAP specific operations.
+ */
+@StaticallyInject
+@Path("/ldap")
+public class LdapRestService extends BaseService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(LdapRestService.class);
+
+  @Inject
+  private static LdapFacade ldapFacade;
+
+  @Inject
+  private static LdapConfigurationFactory ldapConfigurationFactory;
+
+  @POST
+  @ApiIgnore // until documented
+  @Path("/action") // todo this needs to be moved under the resource
+  @Consumes(MediaType.APPLICATION_JSON)
+  public Response validateConfiguration(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
+
+    Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
+    try {
+
+      validateRequest(ldapCheckConfigurationRequest);
+
+      AmbariLdapConfiguration ambariLdapConfiguration = ldapConfigurationFactory.createLdapConfiguration(
+        ldapCheckConfigurationRequest.getAmbariConfiguration().getData().iterator().next());
+
+      switch (ldapCheckConfigurationRequest.getRequestInfo().getAction()) {
+        case "test-connection":
+
+          LOGGER.info("Testing connection to the LDAP server ...");
+          ldapFacade.checkConnection(ambariLdapConfiguration);
+
+          break;
+        case "test-attributes":
+
+          LOGGER.info("Testing LDAP attributes ....");
+          ldapFacade.checkLdapAttibutes(ldapCheckConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
+
+          break;
+        case "detect-attributes":
+
+          LOGGER.info("Detecting LDAP attributes ...");
+          ldapFacade.detectAttributes(ambariLdapConfiguration);
+
+          break;
+        default:
+          LOGGER.warn("No action provided ...");
+          throw new IllegalArgumentException("No request action provided");
+      }
+
+    } catch (Exception e) {
+      result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e));
+    }
+
+    return Response.status(result.getStatus().getStatusCode()).entity(getResultSerializer().serialize(result)).build();
+  }
+
+  private void validateRequest(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
+    String errMsg;
+
+    if (null == ldapCheckConfigurationRequest) {
+      errMsg = "No ldap configuraiton request provided";
+      LOGGER.error(errMsg);
+      throw new IllegalArgumentException(errMsg);
+    }
+
+    if (null == ldapCheckConfigurationRequest.getRequestInfo()) {
+      errMsg = String.format("No request information provided. Request: [%s]", ldapCheckConfigurationRequest);
+      LOGGER.error(errMsg);
+      throw new IllegalArgumentException(errMsg);
+    }
+
+    if (null == ldapCheckConfigurationRequest.getAmbariConfiguration()
+      || ldapCheckConfigurationRequest.getAmbariConfiguration().getData().size() != 1) {
+      errMsg = String.format("No / Invalid configuration data provided. Request: [%s]", ldapCheckConfigurationRequest);
+      LOGGER.error(errMsg);
+      throw new IllegalArgumentException(errMsg);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/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 8988be0..6ceed4a 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
@@ -77,6 +77,7 @@ import org.apache.ambari.server.controller.internal.ViewPermissionResourceProvid
 import org.apache.ambari.server.controller.metrics.ThreadPoolEnabledPropertyProvider;
 import org.apache.ambari.server.controller.utilities.KerberosChecker;
 import org.apache.ambari.server.controller.utilities.KerberosIdentityCleaner;
+import org.apache.ambari.server.ldap.LdapModule;
 import org.apache.ambari.server.metrics.system.MetricsService;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.PersistenceType;
@@ -1061,7 +1062,7 @@ public class AmbariServer {
 
   public static void main(String[] args) throws Exception {
     logStartup();
-    Injector injector = Guice.createInjector(new ControllerModule(), new AuditLoggerModule());
+    Injector injector = Guice.createInjector(new ControllerModule(), new AuditLoggerModule(), new LdapModule());
 
     AmbariServer server = null;
     try {

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index edabcdb..bf790a7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -504,6 +504,7 @@ public class ControllerModule extends AbstractModule {
     install(new FactoryModuleBuilder().implement(CollectionPersisterService.class, CsvFilePersisterService.class).build(CollectionPersisterServiceFactory.class));
 
     install(new FactoryModuleBuilder().build(ConfigureClusterTaskFactory.class));
+
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
new file mode 100644
index 0000000..519f400
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
@@ -0,0 +1,129 @@
+/*
+ * 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.ldap;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.assistedinject.Assisted;
+
+/**
+ * This class is an immutable representation of all the LDAP related configurationMap entries.
+ */
+@Singleton
+public class AmbariLdapConfiguration {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariLdapConfiguration.class);
+
+  /**
+   * Constants representing supported LDAP related property names
+   */
+  public enum LdapConfigProperty {
+    LDAP_CONFIGURED("ambari.ldap.configured"),
+    AUTOMATIC_ATTRIBUTE_DETECTION("ambari.ldap.automatic.attribute.detection"),
+
+    USE_SSL("ambari.ldap.usessl"),
+    LDAP_SERVER_HOST("ambari.ldap.server.host"),
+    LDAP_SERVER_PORT("ambari.ldap.server.port"),
+    BASE_DN("ambari.ldap.base.dn"),
+
+    BIND_ANONIMOUSLY("ambari.ldap.bindanonymously"),
+    MANAGER_DN("ambari.ldap.managerdn"),
+    MANAGER_PASSWORD("ambari.ldap.managerpassword"),
+    USER_OBJECT_CLASS("ambari.ldap.user.object.class"),
+    USER_NAME_ATTRIBUTE("ambari.ldap.user.name.attribute"),
+    USER_SEARCH_BASE("ambari.ldap.user.search.Base"),
+
+    GROUP_OBJECT_CLASS("ambari.ldap.group.object.class"),
+    GROUP_NAME_ATTRIBUTE("ambari.ldap.group.name.attribute"),
+    GROUP_MEMBER_ATTRIBUTE("ambari.ldap.group.member.attribute"),
+    GROUP_SEARCH_BASE("ambari.ldap.group.member.attribute"),
+    DN_ATTRIBUTE("authentication.ldap.dnAttribute");
+
+    private String propertyName;
+
+    LdapConfigProperty(String propertyName) {
+      this.propertyName = propertyName;
+    }
+
+    public String propertyName() {
+      return this.propertyName;
+    }
+  }
+
+  private final Map<String, Object> configurationMap;
+
+  private Object configurationValue(LdapConfigProperty ldapConfigProperty) {
+    Object value = null;
+    if (configurationMap.containsKey(ldapConfigProperty.propertyName)) {
+      value = configurationMap.get(ldapConfigProperty.propertyName);
+    } else {
+      LOGGER.warn("Ldap configuration property [{}] hasn't been set", ldapConfigProperty.propertyName());
+    }
+
+    return value;
+  }
+
+  @Inject
+  public AmbariLdapConfiguration(@Assisted Map<String, Object> configuration) {
+    this.configurationMap = configuration;
+  }
+
+
+  public String ldapServerHost() {
+    return (String) configurationValue(LdapConfigProperty.LDAP_SERVER_HOST);
+  }
+
+  public int ldapServerPort() {
+    return Integer.valueOf((String) configurationValue(LdapConfigProperty.LDAP_SERVER_PORT));
+  }
+
+  public boolean useSSL() {
+    return Boolean.valueOf((String) configurationValue(LdapConfigProperty.USE_SSL));
+  }
+
+  public boolean bindAnonimously() {
+    return Boolean.valueOf((String) configurationValue(LdapConfigProperty.BIND_ANONIMOUSLY));
+  }
+
+  public String managerDn() {
+    return (String) configurationValue(LdapConfigProperty.MANAGER_DN);
+  }
+
+  public String managerPassword() {
+    return (String) configurationValue(LdapConfigProperty.MANAGER_PASSWORD);
+  }
+
+  public boolean automaticAttributeDetection() {
+    return Boolean.valueOf((String) configurationValue(LdapConfigProperty.AUTOMATIC_ATTRIBUTE_DETECTION));
+  }
+
+  public String baseDn() {
+    return (String) configurationValue(LdapConfigProperty.BASE_DN);
+  }
+
+  public String userObjectClass() {
+    return (String) configurationValue(LdapConfigProperty.USER_OBJECT_CLASS);
+  }
+
+  public String userNameAttribute() {
+    return (String) configurationValue(LdapConfigProperty.USER_NAME_ATTRIBUTE);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java
new file mode 100644
index 0000000..bcd6e39
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java
@@ -0,0 +1,21 @@
+/*
+ * 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.ldap;
+
+import java.util.Map;
+
+public interface LdapConfigurationFactory {
+  AmbariLdapConfiguration createLdapConfiguration(Map<String, Object> configuration);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
new file mode 100644
index 0000000..4667721
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ldap;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.service.AmbariLdapException;
+
+/**
+ * Collection of operations for validating ldap configuration.
+ * It's intended to decouple implementations using different libraries.
+ */
+public interface LdapConfigurationValidatorService {
+
+  /**
+   * Tests the connection based on the provided configuration.
+   *
+   * @param configuration the ambari ldap configuration instance
+   * @throws AmbariLdapException if the connection is not possible
+   */
+  void checkConnection(AmbariLdapConfiguration configuration) throws AmbariLdapException;
+
+  /**
+   * Checks whether the group related LDAP attributes in the configuration are correct.
+   *
+   * @param configuration the configuration instance holding the available properties
+   * @throws AmbariException if the attributes are not valid
+   */
+  void checkGroupAttributes(AmbariLdapConfiguration configuration) throws AmbariException;
+
+  /**
+   * Tries to connect to the LDAP server with the given credentials.
+   * Primarily used for testing the user before performing other operations (eg. attribute detection)s
+   *
+   * @param username      the username
+   * @param password      the password
+   * @param configuration the available ldap configuration
+   * @throws AmbariException if the connection couldn't be estabilished
+   */
+  void checkUserAttributes(String username, String password, AmbariLdapConfiguration configuration) throws AmbariException;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
new file mode 100644
index 0000000..625ce8b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
@@ -0,0 +1,37 @@
+/*
+ * 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.ldap;
+
+import org.apache.ambari.server.ldap.service.AmbariLdapFacade;
+import org.apache.ambari.server.ldap.service.LdapFacade;
+import org.apache.ambari.server.ldap.service.ad.AdLdapConfigurationValidatorService;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
+
+/**
+ * GUICE configuration module for setting up LDAP related infrastructure.
+ */
+public class LdapModule extends AbstractModule {
+
+  @Override
+  protected void configure() {
+    bind(LdapFacade.class).to(AmbariLdapFacade.class);
+    bind(LdapConfigurationValidatorService.class).to(AdLdapConfigurationValidatorService.class);
+
+    install(new FactoryModuleBuilder().build(LdapConfigurationFactory.class));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapException.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapException.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapException.java
new file mode 100644
index 0000000..cb38acc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.ldap.service;
+
+public class AmbariLdapException extends Exception {
+  public AmbariLdapException() {
+    super();
+  }
+
+  public AmbariLdapException(String message) {
+    super(message);
+  }
+
+  public AmbariLdapException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public AmbariLdapException(Throwable cause) {
+    super(cause);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
new file mode 100644
index 0000000..abd028a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
@@ -0,0 +1,107 @@
+/*
+ * 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.ldap.service;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class AmbariLdapFacade implements LdapFacade {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariLdapFacade.class);
+
+  private enum Parameters {
+    TEST_USER_NAME("ldap.test.user.name"),
+    TEST_USER_PASSWORD("ldap.test.user.password");
+
+    private String parameterKey;
+
+    Parameters(String parameterKey) {
+      this.parameterKey = parameterKey;
+    }
+
+    private String getParameterKey() {
+      return parameterKey;
+    }
+
+  }
+
+  @Inject
+  private LdapConfigurationValidatorService ldapConfigurationValidatorService;
+
+  @Inject
+  public AmbariLdapFacade() {
+  }
+
+  @Override
+  public void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException {
+    try {
+      LOGGER.info("Validating LDAP connection related configuration based on: {}", ambariLdapConfiguration);
+      ldapConfigurationValidatorService.checkConnection(ambariLdapConfiguration);
+    } catch (AmbariLdapException e) {
+      LOGGER.error("Validating LDAP connection configuration failed", e);
+      throw new AmbariException("Validating LDAP connection configuration failed", e);
+    }
+    LOGGER.info("Validating LDAP connection related configuration: SUCCESS");
+  }
+
+
+  @Override
+  public void detectAttributes(AmbariLdapConfiguration ambariLdapConfiguration) {
+    LOGGER.info("Detecting LDAP configuration attributes ...");
+    throw new UnsupportedOperationException("Not yet implemented");
+  }
+
+  @Override
+  public void checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ldapConfiguration) throws AmbariException {
+    String userName = getTestUserNameFromParameters(parameters);
+    String testUserPass = getTestUserPasswordFromParameters(parameters);
+
+    if (null == userName) {
+      throw new IllegalArgumentException("No test user available for testing LDAP attributes");
+    }
+
+    LOGGER.info("Testing LDAP attributes with test user: {}", userName);
+    ldapConfigurationValidatorService.checkUserAttributes(userName, testUserPass, ldapConfiguration);
+  }
+
+
+  private String getTestUserNameFromParameters(Map<String, Object> parameters) {
+    return (String) parameterValue(parameters, Parameters.TEST_USER_NAME);
+  }
+
+  private String getTestUserPasswordFromParameters(Map<String, Object> parameters) {
+    return (String) parameterValue(parameters, Parameters.TEST_USER_PASSWORD);
+  }
+
+  private Object parameterValue(Map<String, Object> parameters, Parameters parameter) {
+    Object value = null;
+    if (parameters.containsKey(parameter.getParameterKey())) {
+      value = parameters.get(parameter.getParameterKey());
+    } else {
+      LOGGER.warn("Parameter [{}] is missing from parameters", parameter.getParameterKey());
+    }
+    return value;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
new file mode 100644
index 0000000..38553f0
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ldap.service;
+
+import java.util.Map;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+
+/**
+ * The contract defining all the operations required by the application when communicating with an arbitrary LDAP server.
+ * This interface is intended to decouple LDAP specific details from the application.
+ */
+public interface LdapFacade {
+
+  /**
+   * Tests the connection to the LDAP server based on the provided configuration.
+   *
+   * @param ambariLdapConfiguration the available ldap related configuration
+   * @throws AmbariException if the connection fails or other problems occur during the operation
+   */
+  void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException;
+
+
+  /**
+   * Runs the user and group attribute detection algorithms
+   *
+   * @param ambariLdapConfiguration
+   */
+  void detectAttributes(AmbariLdapConfiguration ambariLdapConfiguration);
+
+  /**
+   * Checks user and group related LDAP configuration attributes in the configuration object with the help of the provided parameters
+   *
+   * @param parameters              a map of property name and value pairs holding information to facilitate checking the attributes
+   * @param ambariLdapConfiguration configutration instance with available attributes
+   * @throws AmbariException if the attribute checking fails
+   */
+  void checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java
new file mode 100644
index 0000000..f1abc8b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java
@@ -0,0 +1,18 @@
+/*
+ * 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.ldap.service;
+
+public interface LdapSearchService {
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java
new file mode 100644
index 0000000..11e8655
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java
@@ -0,0 +1,177 @@
+/*
+ * 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.ldap.service.ad;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.service.AmbariLdapException;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Implementation of the validation logic using the Apache Directory API.
+ */
+@Singleton
+public class AdLdapConfigurationValidatorService implements LdapConfigurationValidatorService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(AdLdapConfigurationValidatorService.class);
+
+  @Inject
+  private LdapConfigurationConverter ldapConfigurationConverter;
+
+  /**
+   * Facilitating the instantiation
+   */
+  @Inject
+  public AdLdapConfigurationValidatorService() {
+  }
+
+  @Override
+  public void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+    try {
+      LOGGER.info("Testing the connection based on the configuration: {}", ambariLdapConfiguration);
+
+      LdapConnectionConfig connectionConfig = ldapConfigurationConverter.getLdapConnectionConfig(ambariLdapConfiguration);
+      LdapNetworkConnection connection = new LdapNetworkConnection(connectionConfig);
+
+      if (ambariLdapConfiguration.bindAnonimously()) {
+        LOGGER.debug("Binding anonimously ...");
+        connection.bind();
+      } else {
+        LOGGER.debug("Binding with manager DN and manager password ...");
+        connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
+      }
+
+      if (connection.isConnected()) {
+        LOGGER.info("Successfully connected to the LDAP server.");
+      }
+
+      connection.close();
+
+    } catch (Exception e) {
+      LOGGER.warn("Could not bind to the LDAP server base don the provided configuration ...");
+      throw new AmbariLdapException(e);
+    }
+  }
+
+
+  /**
+   * Checks the user attributes provided in the configuration instance by issuing a search for a (known) test user in the LDAP.
+   * Attributes are considered correct if there is at least one entry found.
+   *
+   * Invalid attributes are signaled by throwing an exception.
+   *
+   * @param username                the username
+   * @param password                the password
+   * @param ambariLdapConfiguration configuration instance holding ldap configuration details
+   * @throws AmbariException if the attributes are not valid or any errors occurs
+   */
+  @Override
+  public void checkUserAttributes(String username, String password, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException {
+    LdapNetworkConnection connection = null;
+    SearchCursor searchCursor = null;
+    try {
+      LOGGER.info("Checking user attributes for user {} r ...", username);
+
+      LdapConnectionConfig connectionConfig = ldapConfigurationConverter.getLdapConnectionConfig(ambariLdapConfiguration);
+      connection = new LdapNetworkConnection(connectionConfig);
+
+
+      if (!ambariLdapConfiguration.bindAnonimously()) {
+        LOGGER.debug("Anonimous binding not supported, binding with the manager detailas...");
+        connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
+      } else {
+        LOGGER.debug("Binding anonimously ...");
+        connection.bind();
+      }
+
+      if (!connection.isConnected()) {
+        LOGGER.error("Not connected to the LDAP server. Connection instance: {}", connection);
+        throw new IllegalStateException("The connection to the LDAP server is not alive");
+      }
+
+      // set up a filter based on the provided attributes
+      String filter = FilterBuilder.and(
+        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
+        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), username))
+        .toString();
+
+      LOGGER.info("Searching for the user: {} using the search filter: {}", username, filter);
+      EntryCursor entryCursor = connection.search(new Dn(ambariLdapConfiguration.baseDn()), filter, SearchScope.SUBTREE);
+
+      // collecting search result entries
+      List<Entry> users = Lists.newArrayList();
+      for (Entry entry : entryCursor) {
+        users.add(entry);
+      }
+
+      // there should be at least one user found
+      if (users.isEmpty()) {
+        String msg = String.format("There are no users found using the filter: [ %s ]. Try changing the attribute values", filter);
+        LOGGER.error(msg);
+        throw new Exception(msg);
+      }
+
+      LOGGER.info("Attibute validation succeeded. Filter: {}", filter);
+
+    } catch (Exception e) {
+
+      LOGGER.error("Error while checking user attributes.");
+      throw new AmbariException("Error while checking user attributes", e);
+
+    } finally {
+
+      LOGGER.debug("Closing the connection and searchresult ...");
+
+      if (null != searchCursor) {
+        searchCursor.close();
+      }
+
+      if (null != connection) {
+        try {
+          connection.close();
+        } catch (IOException e) {
+          LOGGER.error("Exception occurred while closing the connection", e);
+        }
+      }
+
+    }
+  }
+
+  @Override
+  public void checkGroupAttributes(AmbariLdapConfiguration configuration) throws AmbariException {
+
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java
new file mode 100644
index 0000000..a8839f1
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java
@@ -0,0 +1,50 @@
+/*
+ * 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.ldap.service.ad;
+
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Converts between ambari specific ldap types and the 3rd party ldap library
+ */
+@Singleton
+public class LdapConfigurationConverter {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(LdapConfigurationConverter.class);
+
+  /**
+   * Creates a {@link LdapConnectionConfig} instance based on the provided ambari specific configurations
+   *
+   * @param ambariAmbariLdapConfiguration
+   * @return
+   */
+  public LdapConnectionConfig getLdapConnectionConfig(AmbariLdapConfiguration ambariAmbariLdapConfiguration) {
+    LOGGER.debug("Creating a configuration instance based on the ambari configuration: {}", ambariAmbariLdapConfiguration);
+
+    LdapConnectionConfig ldapConnectionConfig = new LdapConnectionConfig();
+    ldapConnectionConfig.setLdapHost(ambariAmbariLdapConfiguration.ldapServerHost());
+    ldapConnectionConfig.setLdapPort(ambariAmbariLdapConfiguration.ldapServerPort());
+    ldapConnectionConfig.setUseSsl(ambariAmbariLdapConfiguration.useSSL());
+
+    //todo set the other values as required
+    return ldapConnectionConfig;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java
new file mode 100644
index 0000000..f20cd1f
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.ldap;
+
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class LDAPServiceTest {
+
+  private static String JSON_STRING = "{\n" +
+    "  \"AmbariConfiguration\": {\n" +
+    "    \"type\": \"ldap-config\",\n" +
+    "    \"data\": [{\n" +
+    "        \"authentication.ldap.primaryUrl\": \"localhost:33389\",\n" +
+    "        \"authentication.ldap.secondaryUrl\": \"localhost:333\",\n" +
+    "        \"authentication.ldap.baseDn\": \"dc=ambari,dc=apache,dc=org\"\n" +
+    "      }]\n" +
+    "  }\n" +
+    "}";
+
+  @Test
+  public void testJaxRsJsonTransformation() throws Exception {
+    // GIVEN
+    ObjectMapper objectMapper = new ObjectMapper();
+
+    Gson gsonJsonProvider = new GsonBuilder().create();
+
+
+    // WHEN
+    LdapCheckConfigurationRequest ldapCheckConfigurationRequest = gsonJsonProvider.fromJson(JSON_STRING, LdapCheckConfigurationRequest.class);
+    // LdapCheckConfigurationRequest ldapCheckConfigurationRequest = objectMapper.readValue(JSON_STRING, LdapCheckConfigurationRequest.class);
+
+    // THEN
+    Assert.assertNotNull(ldapCheckConfigurationRequest);
+
+  }
+
+
+  @Test
+  public void testLdapConnection() throws Exception {
+    // GIVEN
+    LdapConnection connection = new LdapNetworkConnection("localhost", 389);
+
+    // WHEN
+    connection.bind();
+    // THEN
+
+  }
+
+
+  @Test
+  public void testLdapConnectionConfigs() throws Exception {
+    // GIVEN
+    LdapConnectionConfig config = new LdapConnectionConfig();
+    config.setLdapHost("localhost");
+    config.setLdapPort(389);
+
+    // WHEN
+    LdapConnection connection = new LdapNetworkConnection(config);
+
+    // THEN
+    connection.anonymousBind();
+
+    Assert.assertNotNull(connection);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/43dbbc95/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java
new file mode 100644
index 0000000..0f57099
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.ldap.service.ad;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.Response;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchResultEntry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class AdLdapConfigurationValidatorServiceTest {
+  private static final Logger LOGGER = LoggerFactory.getLogger(AdLdapConfigurationValidatorService.class);
+  private static final String TEST_USER = "Jocika10";
+
+  LdapConfigurationValidatorService ldapConfigurationValidatorService = new AdLdapConfigurationValidatorService();
+
+
+  @Test
+  public void testCheckAttributes() throws Exception {
+
+    // WHEN
+    LdapConnectionConfig config = new LdapConnectionConfig();
+    config.setLdapHost("localhost");
+    config.setLdapPort(389);
+    LdapConnection connection = new LdapNetworkConnection(config);
+
+    // THEN
+    connection.anonymousBind();
+
+
+    EntryCursor cursor = connection.search("dc=dev,dc=local", "(objectclass=*)", SearchScope.ONELEVEL);
+
+    for (Entry entry : cursor) {
+      assertNotNull(entry);
+      System.out.println(entry);
+    }
+
+    cursor.close();
+
+  }
+
+  @Test
+  public void testCheckUserAttributes() throws Exception {
+    Map<String, Object> ldapPropsMap = Maps.newHashMap();
+
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), true);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "localhost");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=dev,dc=local");
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
+
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
+
+
+    try {
+      LOGGER.info("Authenticating user {} against the LDAP server ...", TEST_USER);
+      LdapConfigurationConverter ldapConfigurationConverter = new LdapConfigurationConverter();
+
+      LdapConnectionConfig connectionConfig = ldapConfigurationConverter.getLdapConnectionConfig(ambariLdapConfiguration);
+      LdapNetworkConnection connection = new LdapNetworkConnection(connectionConfig);
+
+      String filter = FilterBuilder.and(
+        FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
+        FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), TEST_USER))
+        .toString();
+
+      SearchRequest searchRequest = new SearchRequestImpl();
+      searchRequest.setBase(new Dn(ambariLdapConfiguration.baseDn()));
+      searchRequest.setFilter(filter);
+      searchRequest.setScope(SearchScope.SUBTREE);
+
+      LOGGER.info("loking up user: {} based on the filtr: {}", TEST_USER, filter);
+
+      connection.bind();
+      SearchCursor searchCursor = connection.search(searchRequest);
+
+      while (searchCursor.next()) {
+        Response response = searchCursor.get();
+
+        // process the SearchResultEntry
+        if (response instanceof SearchResultEntry) {
+          Entry resultEntry = ((SearchResultEntry) response).getEntry();
+          System.out.println(resultEntry);
+        }
+      }
+
+      searchCursor.close();
+
+    } catch (Exception e) {
+      throw new AmbariException("Error during user authentication check", e);
+    }
+
+  }
+
+}
\ No newline at end of file


[36/38] ambari git commit: AMBARI-21307 Added the supported ldap properties to the code. Refactored existing code relying on these properties

Posted by lp...@apache.org.
AMBARI-21307 Added the supported ldap properties to the code. Refactored existing code relying on these properties


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/e4a80b18
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/e4a80b18
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/e4a80b18

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: e4a80b18b02f4b8ce0f0d19be1629fc19219cf7a
Parents: 2750e62
Author: lpuskas <lp...@apache.org>
Authored: Fri Sep 8 13:57:25 2017 +0300
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:32 2017 +0200

----------------------------------------------------------------------
 .../server/ldap/AmbariLdapConfiguration.java    | 189 ++++++++++++-------
 .../AmbariLdapConfigurationProvider.java        |   6 +-
 .../server/ldap/service/AmbariLdapFacade.java   |  10 +-
 .../service/LdapAttributeDetectionService.java  |  43 +++++
 .../ambari/server/ldap/service/LdapFacade.java  |   2 +-
 .../ads/DefaultAttributeDetectionService.java   |  47 +++++
 .../ads/DefaultLdapConfigurationService.java    |   4 +-
 .../ads/DefaultLdapConnectionService.java       |   4 +-
 .../DefaultAttributeDetectionServiceTest.java   | 102 ++++++++++
 .../DefaultLdapConfigurationServiceTest.java    |  30 ++-
 10 files changed, 348 insertions(+), 89 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/e4a80b18/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
index e913e77..76faeed 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
@@ -34,63 +34,67 @@ public class AmbariLdapConfiguration {
   /**
    * Constants representing supported LDAP related property names
    */
-  public enum LdapConfigProperty {
-    LDAP_CONFIGURED("ambari.ldap.configured"),
-    AUTOMATIC_ATTRIBUTE_DETECTION("ambari.ldap.automatic.attribute.detection"),
-    USE_SSL("ambari.ldap.usessl"),
-    LDAP_SERVER_HOST("ambari.ldap.server.host"),
-    LDAP_SERVER_PORT("ambari.ldap.server.port"),
-    LDAP_TRUSTSTORE("ambari.ldap.truststore"),
-    LDAP_TRUSTSTORE_TYPE("ambari.ldap.truststore.type"),
-    LDAP_TRUSTSTORE_PATH("ambari.ldap.truststore.path"),
-    LDAP_TRUSTSTORE_PASSWORD("ambari.ldap.truststore.password"),
-    BASE_DN("ambari.ldap.bind.dn"),
-    REFERRAL("ambari.ldap.referral"),
-    PAGINATION_ENABLED("ambari.ldap.pagination.enabled"),
-
-    BIND_ANONIMOUSLY("ambari.ldap.bindanonymously"),
-    MANAGER_DN("ambari.ldap.managerdn"),
-    MANAGER_PASSWORD("ambari.ldap.managerpassword"),
-    USER_OBJECT_CLASS("ambari.ldap.user.object.class"),
-    USER_NAME_ATTRIBUTE("ambari.ldap.user.name.attribute"),
-    USER_NAME_FORCE_LOWERCASE("ambari.ldap.username.force.lowercase"),
-    USER_SEARCH_BASE("ambari.ldap.user.search.base"),
-    SYNC_USER_MEMBER_REPLACE_PATTERN("ambari.ldap.sync.user.member.replacepattern"),
-    SYNC_USER_MEMBER_FILTER("ambari.ldap.sync.user.member_filter"),
-
-    ADMIN_GROUP_MAPPING_RULES ("ambari.ldap.admin.group.mappingrules"),
-    GROUP_OBJECT_CLASS("ambari.ldap.group.object.class"),
-    GROUP_NAME_ATTRIBUTE("ambari.ldap.group.name.attribute"),
-    GROUP_MEMBER_ATTRIBUTE("ambari.ldap.group.member.attribute"),
-    GROUP_SEARCH_BASE("ambari.ldap.group.search.base"),
-    SYNC_GROUP_MEMBER_REPLACE_PATTERN("ambari.ldap.sync.group.member.replacepattern"),
-    SYNC_GROUP_MEMBER_FILTER("ambari.ldap.sync.group.member_filter"),
-    DN_ATTRIBUTE("authentication.ldap.dnAttribute"),
-
-    TEST_USER_NAME("ambari.ldap.test.user.name"),
-    TEST_USER_PASSWORD("ambari.ldap.test.user.password");
+  public enum AmbariLdapConfig {
+
+    LDAP_ENABLED("ambari.ldap.authentication.enabled"),
+    SERVER_HOST("ambari.ldap.connectivity.server.host"),
+    SERVER_PORT("ambari.ldap.connectivity.server.port"),
+    USE_SSL("ambari.ldap.connectivity.use_ssl"),
+
+    TRUST_STORE("ambari.ldap.connectivity.trust_store"),
+    TRUST_STORE_TYPE("ambari.ldap.connectivity.trust_store.type"),
+    TRUST_STORE_PATH("ambari.ldap.connectivity.trust_store.path"),
+    TRUST_STORE_PASSWORD("ambari.ldap.connectivity.trust_store.password"),
+    ANONYMOUS_BIND("ambari.ldap.connectivity.anonymous_bind"),
+
+    BIND_DN("ambari.ldap.connectivity.bind_dn"),
+    BIND_PASSWORD("ambari.ldap.connectivity.bind_password"),
+
+    ATTR_DETECTION("ambari.ldap.attributes.detection"), // manual | auto
+
+    DN_ATTRIBUTE("ambari.ldap.attributes.dn_attr"),
+
+    USER_OBJECT_CLASS("ambari.ldap.attributes.user.object_class"),
+    USER_NAME_ATTRIBUTE("ambari.ldap.attributes.user.name_attr"),
+    USER_SEARCH_BASE("ambari.ldap.attributes.user.search_base"),
+
+    GROUP_OBJECT_CLASS("ambari.ldap.attributes.group.object_class"),
+    GROUP_NAME_ATTRIBUTE("ambari.ldap.attributes.group.name_attr"),
+    GROUP_MEMBER_ATTRIBUTE("ambari.ldap.attributes.group.member_attr"),
+    GROUP_SEARCH_BASE("ambari.ldap.attributes.user.search_base"),
+
+    USER_SEARCH_FILTER("ambari.ldap.advanced.user_search_filter"),
+    USER_MEMBER_REPLACE_PATTERN("ambari.ldap.advanced.user_member_replace_pattern"),
+    USER_MEMBER_FILTER("ambari.ldap.advanced.user_member_filter"),
+
+    GROUP_SEARCH_FILTER("ambari.ldap.advanced.group_search_filter"),
+    GROUP_MEMBER_REPLACE_PATTERN("ambari.ldap.advanced.group_member_replace_pattern"),
+    GROUP_MEMBER_FILTER("ambari.ldap.advanced.group_member_filter"),
+
+    FORCE_LOWERCASE_USERNAMES("ambari.ldap.advanced.force_lowercase_usernames"),
+    REFERRAL_HANDLING("ambari.ldap.advanced.referrals"), // folow
+    PAGINATION_ENABLED("ambari.ldap.advanced.pagination_enabled"); // true | false
 
     private String propertyName;
 
-    LdapConfigProperty(String propertyName) {
-      this.propertyName = propertyName;
+    AmbariLdapConfig(String propName) {
+      this.propertyName = propName;
     }
 
-    public String propertyName() {
+    public String key() {
       return this.propertyName;
     }
   }
 
   private final Map<String, Object> configurationMap;
 
-  private Object configurationValue(LdapConfigProperty ldapConfigProperty) {
+  private Object configValue(AmbariLdapConfig ambariLdapConfig) {
     Object value = null;
-    if (configurationMap.containsKey(ldapConfigProperty.propertyName)) {
-      value = configurationMap.get(ldapConfigProperty.propertyName);
+    if (configurationMap.containsKey(ambariLdapConfig.key())) {
+      value = configurationMap.get(ambariLdapConfig.key());
     } else {
-      LOGGER.warn("Ldap configuration property [{}] hasn't been set", ldapConfigProperty.propertyName());
+      LOGGER.warn("Ldap configuration property [{}] hasn't been set", ambariLdapConfig.key());
     }
-
     return value;
   }
 
@@ -99,65 +103,120 @@ public class AmbariLdapConfiguration {
     this.configurationMap = configuration;
   }
 
+  public boolean ldapEnabled() {
+    return Boolean.valueOf((String) configValue(AmbariLdapConfig.LDAP_ENABLED));
+  }
 
-  public String ldapServerHost() {
-    return (String) configurationValue(LdapConfigProperty.LDAP_SERVER_HOST);
+  public String serverHost() {
+    return (String) configValue(AmbariLdapConfig.SERVER_HOST);
   }
 
-  public int ldapServerPort() {
-    return Integer.valueOf((String) configurationValue(LdapConfigProperty.LDAP_SERVER_PORT));
+  public int serverPort() {
+    return Integer.valueOf((String) configValue(AmbariLdapConfig.SERVER_PORT));
   }
 
   public boolean useSSL() {
-    return Boolean.valueOf((String) configurationValue(LdapConfigProperty.USE_SSL));
+    return Boolean.valueOf((String) configValue(AmbariLdapConfig.USE_SSL));
+  }
+
+  public String trustStore() {
+    return (String) configValue(AmbariLdapConfig.TRUST_STORE);
+  }
+
+  public String trustStoreType() {
+    return (String) configValue(AmbariLdapConfig.TRUST_STORE_TYPE);
+  }
+
+  public String trustStorePath() {
+    return (String) configValue(AmbariLdapConfig.TRUST_STORE_PATH);
+  }
+
+  public String trustStorePassword() {
+    return (String) configValue(AmbariLdapConfig.TRUST_STORE_PASSWORD);
   }
 
-  public boolean bindAnonimously() {
-    return Boolean.valueOf((String) configurationValue(LdapConfigProperty.BIND_ANONIMOUSLY));
+  public boolean anonymousBind() {
+    return Boolean.valueOf((String) configValue(AmbariLdapConfig.ANONYMOUS_BIND));
   }
 
-  public String managerDn() {
-    return (String) configurationValue(LdapConfigProperty.MANAGER_DN);
+  public String bindDn() {
+    return (String) configValue(AmbariLdapConfig.BIND_DN);
   }
 
-  public String managerPassword() {
-    return (String) configurationValue(LdapConfigProperty.MANAGER_PASSWORD);
+  public String bindPassword() {
+    return (String) configValue(AmbariLdapConfig.BIND_PASSWORD);
   }
 
-  public boolean automaticAttributeDetection() {
-    return Boolean.valueOf((String) configurationValue(LdapConfigProperty.AUTOMATIC_ATTRIBUTE_DETECTION));
+  public String attributeDetection() {
+    return (String) configValue(AmbariLdapConfig.ATTR_DETECTION);
   }
 
-  public String baseDn() {
-    return (String) configurationValue(LdapConfigProperty.BASE_DN);
+  public String dnAttribute() {
+    return (String) configValue(AmbariLdapConfig.DN_ATTRIBUTE);
   }
 
   public String userObjectClass() {
-    return (String) configurationValue(LdapConfigProperty.USER_OBJECT_CLASS);
+    return (String) configValue(AmbariLdapConfig.USER_OBJECT_CLASS);
   }
 
   public String userNameAttribute() {
-    return (String) configurationValue(LdapConfigProperty.USER_NAME_ATTRIBUTE);
+    return (String) configValue(AmbariLdapConfig.USER_NAME_ATTRIBUTE);
   }
 
   public String userSearchBase() {
-    return (String) configurationValue(LdapConfigProperty.USER_SEARCH_BASE);
+    return (String) configValue(AmbariLdapConfig.USER_SEARCH_BASE);
   }
 
   public String groupObjectClass() {
-    return (String) configurationValue(LdapConfigProperty.GROUP_OBJECT_CLASS);
+    return (String) configValue(AmbariLdapConfig.GROUP_OBJECT_CLASS);
   }
 
   public String groupNameAttribute() {
-    return (String) configurationValue(LdapConfigProperty.GROUP_NAME_ATTRIBUTE);
+    return (String) configValue(AmbariLdapConfig.GROUP_NAME_ATTRIBUTE);
   }
 
   public String groupMemberAttribute() {
-    return (String) configurationValue(LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE);
+    return (String) configValue(AmbariLdapConfig.GROUP_MEMBER_ATTRIBUTE);
   }
 
   public String groupSearchBase() {
-    return (String) configurationValue(LdapConfigProperty.GROUP_SEARCH_BASE);
+    return (String) configValue(AmbariLdapConfig.GROUP_SEARCH_BASE);
+  }
+
+  public String userSearchFilter() {
+    return (String) configValue(AmbariLdapConfig.USER_SEARCH_FILTER);
+  }
+
+  public String userMemberReplacePattern() {
+    return (String) configValue(AmbariLdapConfig.USER_MEMBER_REPLACE_PATTERN);
+  }
+
+  public String userMemberFilter() {
+    return (String) configValue(AmbariLdapConfig.USER_MEMBER_FILTER);
+  }
+
+  public String groupSearchFilter() {
+    return (String) configValue(AmbariLdapConfig.GROUP_SEARCH_FILTER);
+  }
+
+  public String groupMemberReplacePattern() {
+    return (String) configValue(AmbariLdapConfig.GROUP_MEMBER_REPLACE_PATTERN);
+  }
+
+  public String groupMemberFilter() {
+    return (String) configValue(AmbariLdapConfig.GROUP_MEMBER_FILTER);
+  }
+
+  public boolean forceLowerCaseUserNames() {
+    return Boolean.valueOf((String) configValue(AmbariLdapConfig.FORCE_LOWERCASE_USERNAMES));
+  }
+
+  public boolean paginationEnabled() {
+    return Boolean.valueOf((String) configValue(AmbariLdapConfig.PAGINATION_ENABLED));
+  }
+
+  public String referralHandling() {
+    return (String) configValue(AmbariLdapConfig.REFERRAL_HANDLING);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4a80b18/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
index 7f3e8a9..80ed828 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
@@ -24,6 +24,7 @@ import javax.inject.Singleton;
 import org.apache.ambari.server.events.AmbariLdapConfigChangedEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationFactory;
 import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
 import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
 import org.apache.ambari.server.security.authorization.AmbariLdapAuthenticationProvider;
@@ -55,6 +56,9 @@ public class AmbariLdapConfigurationProvider implements Provider<AmbariLdapConfi
   @Inject
   private Provider<AmbariConfigurationDAO> ambariConfigurationDAOProvider;
 
+  @Inject
+  private LdapConfigurationFactory ldapConfigurationFactory;
+
   private Gson gson = new GsonBuilder().create();
 
   @Inject
@@ -95,7 +99,7 @@ public class AmbariLdapConfigurationProvider implements Provider<AmbariLdapConfi
 
     if (configEntity != null) {
       Set propertyMaps = gson.fromJson(configEntity.getConfigurationBaseEntity().getConfigurationData(), Set.class);
-      instance = new AmbariLdapConfiguration((Map<String, Object>) propertyMaps.iterator().next());
+      instance = ldapConfigurationFactory.createLdapConfiguration((Map<String, Object>) propertyMaps.iterator().next());
     }
 
     LOGGER.info("Loaded LDAP configuration instance: [ {} ]", instance);

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4a80b18/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
index 90a5ba7..16bf6b7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
@@ -55,6 +55,9 @@ public class AmbariLdapFacade implements LdapFacade {
   @Inject
   private LdapConnectionService ldapConnectionService;
 
+  @Inject
+  private LdapAttributeDetectionService ldapAttributeDetectionService;
+
   //todo remove this, added for testing purposes only
   @Inject
   private Provider<AmbariLdapConfiguration> ambariLdapConfigurationProvider;
@@ -78,9 +81,12 @@ public class AmbariLdapFacade implements LdapFacade {
 
 
   @Override
-  public void detectAttributes(AmbariLdapConfiguration ambariLdapConfiguration) {
+  public AmbariLdapConfiguration detectAttributes(AmbariLdapConfiguration ambariLdapConfiguration) {
     LOGGER.info("Detecting LDAP configuration attributes ...");
-    LOGGER.info("LDAP config: {}", ambariLdapConfigurationProvider.get());
+
+    LdapConnection connection = ldapConnectionService.createLdapConnection(ambariLdapConfiguration);
+    ambariLdapConfiguration = ldapAttributeDetectionService.detectLdapUserAttributes(connection, ambariLdapConfiguration);
+    return ambariLdapConfiguration;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4a80b18/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapAttributeDetectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapAttributeDetectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapAttributeDetectionService.java
new file mode 100644
index 0000000..70a8977
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapAttributeDetectionService.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ldap.service;
+
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.directory.ldap.client.api.LdapConnection;
+
+/**
+ * Contract defining operations to detect user and group attributes.
+ */
+public interface LdapAttributeDetectionService {
+
+  /**
+   * Decorates the passed in configuration with the detected ldap user attribute values
+   *
+   * @param ldapConnection          the connection instance to LDAP
+   * @param ambariLdapConfiguration configuration instance holding connection details
+   * @return the configuration decorated with user related attributes
+   */
+  AmbariLdapConfiguration detectLdapUserAttributes(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration);
+
+  /**
+   * Decorates the passed in configuration with the detected ldap group attribute values
+   *
+   * @param ldapConnection          the connection instance to LDAP
+   * @param ambariLdapConfiguration configuration instance holding connection details
+   * @return the configuration decorated with group related attributes
+   */
+  AmbariLdapConfiguration detectLdapGroupAttributes(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration);
+}
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4a80b18/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
index eadff7d..76b16c4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
@@ -39,7 +39,7 @@ public interface LdapFacade {
    *
    * @param ambariLdapConfiguration
    */
-  void detectAttributes(AmbariLdapConfiguration ambariLdapConfiguration);
+  AmbariLdapConfiguration detectAttributes(AmbariLdapConfiguration ambariLdapConfiguration);
 
   /**
    * Checks user and group related LDAP configuration attributes in the configuration object with the help of the provided parameters

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4a80b18/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
new file mode 100644
index 0000000..55d0765
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionService.java
@@ -0,0 +1,47 @@
+/*
+ * 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.ldap.service.ads;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.service.LdapAttributeDetectionService;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class DefaultAttributeDetectionService implements LdapAttributeDetectionService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAttributeDetectionService.class);
+
+  @Inject
+  public DefaultAttributeDetectionService() {
+  }
+
+  @Override
+  public AmbariLdapConfiguration detectLdapUserAttributes(LdapConnection connection, AmbariLdapConfiguration ambariLdapConfiguration) {
+    LOGGER.info("Detecting LDAP user attributes ...");
+
+    return null;
+  }
+
+  @Override
+  public AmbariLdapConfiguration detectLdapGroupAttributes(LdapConnection connection, AmbariLdapConfiguration ambariLdapConfiguration) {
+    LOGGER.info("Detecting LDAP group attributes ...");
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4a80b18/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
index abc9201..db8c77f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
@@ -186,9 +186,9 @@ public class DefaultLdapConfigurationService implements LdapConfigurationService
    */
   private void bind(AmbariLdapConfiguration ambariLdapConfiguration, LdapConnection connection) throws LdapException {
     LOGGER.info("Connecting to LDAP ....");
-    if (!ambariLdapConfiguration.bindAnonimously()) {
+    if (!ambariLdapConfiguration.anonymousBind()) {
       LOGGER.debug("Anonimous binding not supported, binding with the manager detailas...");
-      connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
+      connection.bind(ambariLdapConfiguration.bindDn(), ambariLdapConfiguration.bindPassword());
     } else {
       LOGGER.debug("Binding anonimously ...");
       connection.bind();

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4a80b18/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java
index ced52fc..f39df54 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java
@@ -52,8 +52,8 @@ public class DefaultLdapConnectionService implements LdapConnectionService {
     LOGGER.debug("Creating a configuration instance based on the ambari configuration: {}", ambariAmbariLdapConfiguration);
 
     LdapConnectionConfig ldapConnectionConfig = new LdapConnectionConfig();
-    ldapConnectionConfig.setLdapHost(ambariAmbariLdapConfiguration.ldapServerHost());
-    ldapConnectionConfig.setLdapPort(ambariAmbariLdapConfiguration.ldapServerPort());
+    ldapConnectionConfig.setLdapHost(ambariAmbariLdapConfiguration.serverHost());
+    ldapConnectionConfig.setLdapPort(ambariAmbariLdapConfiguration.serverPort());
     ldapConnectionConfig.setUseSsl(ambariAmbariLdapConfiguration.useSSL());
 
     // todo set the other values as required

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4a80b18/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
new file mode 100644
index 0000000..5b3ac20
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultAttributeDetectionServiceTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.ldap.service.ads;
+
+
+import java.util.Map;
+
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.service.LdapConnectionService;
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.easymock.EasyMockRule;
+import org.easymock.TestSubject;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class DefaultAttributeDetectionServiceTest {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAttributeDetectionServiceTest.class);
+
+  @Rule
+  public EasyMockRule mocks = new EasyMockRule(this);
+
+  private AmbariLdapConfiguration testLdapConfiguration;
+  private LdapConnection connection;
+
+  @TestSubject
+  private DefaultAttributeDetectionService attributeDetectionService = new DefaultAttributeDetectionService();
+
+  @Before
+  public void before() {
+
+    Map<String, Object> initialProps = Maps.newHashMap();
+    initialProps.put(AmbariLdapConfiguration.AmbariLdapConfig.BIND_DN.key(), "");
+    testLdapConfiguration = new AmbariLdapConfiguration(initialProps);
+  }
+
+  @Test
+  public void testShouldUserNameAttributeBeDetectedWhenSearchReturnsValidUsers() throws Exception {
+    // GIVEN
+// a set of entries returned from the LDAP search
+
+    // WHEN
+    AmbariLdapConfiguration ambariLdapConfiguration = attributeDetectionService.detectLdapUserAttributes(connection, testLdapConfiguration);
+
+    // THEN
+    Assert.assertNotNull(ambariLdapConfiguration);
+    Assert.assertEquals("The username attribute is not the expected", "uid", ambariLdapConfiguration.userNameAttribute());
+
+  }
+
+
+  private Map<String, Object> getTestPropertiesMap() {
+    Map<String, Object> ldapPropsMap = Maps.newHashMap();
+
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.ANONYMOUS_BIND.key(), "true");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.SERVER_HOST.key(), "ldap.forumsys.com");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.SERVER_PORT.key(), "389");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.BIND_DN.key(), "dc=example,dc=com");
+
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_OBJECT_CLASS.key(), SchemaConstants.PERSON_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_NAME_ATTRIBUTE.key(), SchemaConstants.UID_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_SEARCH_BASE.key(), "dc=example,dc=com");
+
+    return ldapPropsMap;
+
+  }
+
+  @Test
+  public void functionalTest() throws Exception {
+    // GIVEN
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(getTestPropertiesMap());
+    LdapConnectionService connectionService = new DefaultLdapConnectionService();
+    LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration);
+
+
+    // WHEN
+    AmbariLdapConfiguration config = attributeDetectionService.detectLdapUserAttributes(ldapConnection, ambariLdapConfiguration);
+
+    // THEN
+
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4a80b18/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
index b5978a5..e023c6c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
@@ -74,14 +74,14 @@ public class DefaultLdapConfigurationServiceTest {
     // GIVEN
     Map<String, Object> ldapPropsMap = Maps.newHashMap();
 
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.ANONYMOUS_BIND.key(), "true");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.SERVER_HOST.key(), "ldap.forumsys.com");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.SERVER_PORT.key(), "389");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.BIND_DN.key(), "dc=example,dc=com");
 
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_SEARCH_BASE.propertyName(), "dc=example,dc=com");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_OBJECT_CLASS.key(), SchemaConstants.PERSON_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_NAME_ATTRIBUTE.key(), SchemaConstants.UID_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_SEARCH_BASE.key(), "dc=example,dc=com");
 
 
     AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
@@ -96,16 +96,14 @@ public class DefaultLdapConfigurationServiceTest {
     // GIVEN
     Map<String, Object> ldapPropsMap = Maps.newHashMap();
 
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.ANONYMOUS_BIND.key(), "true");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.SERVER_HOST.key(), "ldap.forumsys.com");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.SERVER_PORT.key(), "389");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.BIND_DN.key(), "dc=example,dc=com");
 
-
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE.propertyName(), SchemaConstants.UNIQUE_MEMBER_AT);
-    ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_SEARCH_BASE.propertyName(), "dc=example,dc=com");
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_OBJECT_CLASS.key(), SchemaConstants.PERSON_OC);
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_NAME_ATTRIBUTE.key(), SchemaConstants.UID_AT);
+    ldapPropsMap.put(AmbariLdapConfiguration.AmbariLdapConfig.USER_SEARCH_BASE.key(), "dc=example,dc=com");
 
 
     AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);


[14/38] ambari git commit: AMBARI-21934. All config versions for a config group are disabled right after renaming the config group (akovalenko)

Posted by lp...@apache.org.
AMBARI-21934. All config versions for a config group are disabled right after renaming the config group (akovalenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/fa0ecc48
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/fa0ecc48
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/fa0ecc48

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: fa0ecc48ac68335fcce06bd41d473cfcfcfd475e
Parents: c6e19b7
Author: Aleksandr Kovalenko <ak...@hortonworks.com>
Authored: Tue Sep 12 16:07:46 2017 +0300
Committer: Aleksandr Kovalenko <ak...@hortonworks.com>
Committed: Wed Sep 13 14:15:05 2017 +0300

----------------------------------------------------------------------
 .../controllers/main/service/manage_config_groups_controller.js | 4 ++--
 ambari-web/app/views/common/configs/config_history_flow.js      | 5 ++---
 2 files changed, 4 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/fa0ecc48/ambari-web/app/controllers/main/service/manage_config_groups_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/manage_config_groups_controller.js b/ambari-web/app/controllers/main/service/manage_config_groups_controller.js
index a260652..cca3d89 100644
--- a/ambari-web/app/controllers/main/service/manage_config_groups_controller.js
+++ b/ambari-web/app/controllers/main/service/manage_config_groups_controller.js
@@ -956,8 +956,8 @@ App.ManageConfigGroupsController = Em.Controller.extend(App.ConfigOverridable, {
               if (errors.length > 0) {
                 self.get('subViewController').set('errorMessage', errors.join(". "));
               } else {
-                if (!self.get('isAddService') && !self.get('isInstaller') && !modifiedConfigGroups.toCreate.everyProperty('properties.length', 0)) {
-                  //update service config versions only if it is service configs page and at least one newly created group had properties
+                if (!self.get('isAddService') && !self.get('isInstaller')) {
+                  //update service config versions only if it is service configs page
                   App.router.get('mainServiceInfoConfigsController').loadServiceConfigVersions().done(function () {
                     self.updateConfigGroupOnServicePage();
                     self.hide();

http://git-wip-us.apache.org/repos/asf/ambari/blob/fa0ecc48/ambari-web/app/views/common/configs/config_history_flow.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/config_history_flow.js b/ambari-web/app/views/common/configs/config_history_flow.js
index 6903e8e..32a5e71 100644
--- a/ambari-web/app/views/common/configs/config_history_flow.js
+++ b/ambari-web/app/views/common/configs/config_history_flow.js
@@ -95,13 +95,12 @@ App.ConfigHistoryFlowView = Em.View.extend({
   shortNotes: Em.computed.truncate('displayedServiceVersion.notes', 100, 100),
 
   serviceVersions: function () {
-    var groupName = this.get('controller.selectedConfigGroup.isDefault') ? App.ServiceConfigGroup.defaultGroupName
-        : this.get('controller.selectedConfigGroup.name');
+    var isDefaultGroupSelected = this.get('controller.selectedConfigGroup.isDefault');
     var groupId = this.get('controller.selectedConfigGroup.id');
     var self = this;
 
     this.get('allServiceVersions').forEach(function (version) {
-      version.set('isDisabled', !(version.get('groupName') === groupName));
+      version.set('isDisabled', !(version.get('groupId') === groupId || isDefaultGroupSelected && version.get('groupName') === App.ServiceConfigGroup.defaultGroupName));
     }, this);
 
     var serviceVersions = this.get('allServiceVersions').filter(function(s) {


[23/38] ambari git commit: AMBARI-21307 Added new resource related changes to the db creation ddl-s

Posted by lp...@apache.org.
AMBARI-21307 Added new resource related changes to the db creation ddl-s


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/885761f4
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/885761f4
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/885761f4

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 885761f439756f8ce364a7238b7550c3820b1892
Parents: a02052d
Author: lpuskas <lp...@apache.org>
Authored: Thu Jul 6 18:15:18 2017 +0200
Committer: lpuskas <la...@sequenceiq.com>
Committed: Thu Sep 14 16:37:29 2017 +0200

----------------------------------------------------------------------
 .../AmbariConfigurationResourceProvider.java    | 12 ++--
 .../server/orm/dao/AmbariConfigurationDAO.java  | 65 ++------------------
 .../apache/ambari/server/orm/dao/DaoUtils.java  | 13 +---
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  | 21 +++++++
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  | 20 ++++++
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 20 ++++++
 .../resources/Ambari-DDL-Postgres-CREATE.sql    | 14 ++---
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 20 ++++++
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   | 20 ++++++
 9 files changed, 120 insertions(+), 85 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/885761f4/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
index 5e5af9e..e8f186d 100644
--- 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
@@ -97,14 +97,14 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
     }
   }
 
-  private static Set<String> properties = Sets.newHashSet(
+  private static Set<String> PROPERTIES = Sets.newHashSet(
     ResourcePropertyId.ID.getPropertyId(),
     ResourcePropertyId.TYPE.getPropertyId(),
     ResourcePropertyId.VERSION.getPropertyId(),
     ResourcePropertyId.VERSION_TAG.getPropertyId(),
     ResourcePropertyId.DATA.getPropertyId());
 
-  private static Map<Resource.Type, String> pkPropertyMap = Collections.unmodifiableMap(
+  private static Map<Resource.Type, String> PK_PROPERTY_MAP = Collections.unmodifiableMap(
     new HashMap<Resource.Type, String>() {{
       put(Resource.Type.AmbariConfiguration, ResourcePropertyId.ID.getPropertyId());
     }}
@@ -117,7 +117,7 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
   private Gson gson;
 
   protected AmbariConfigurationResourceProvider() {
-    super(properties, pkPropertyMap);
+    super(PROPERTIES, PK_PROPERTY_MAP);
     setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION));
     setRequiredDeleteAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION));
 
@@ -126,7 +126,7 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
 
   @Override
   protected Set<String> getPKPropertyIds() {
-    return Sets.newHashSet("AmbariConfiguration/id");
+    return Sets.newHashSet(ResourcePropertyId.ID.getPropertyId());
   }
 
   @Override
@@ -137,7 +137,7 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
     AmbariConfigurationEntity ambariConfigurationEntity = getEntityFromRequest(request);
 
     LOGGER.info("Persisting new ambari configuration: {} ", ambariConfigurationEntity);
-    ambariConfigurationDAO.persist(ambariConfigurationEntity);
+    ambariConfigurationDAO.create(ambariConfigurationEntity);
 
     return getRequestStatus(null);
   }
@@ -170,7 +170,7 @@ public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResou
     } else {
       LOGGER.debug("Deleting amari configuration with id: {}", idFromRequest);
       try {
-        ambariConfigurationDAO.deleteById(idFromRequest);
+        ambariConfigurationDAO.removeByPK(idFromRequest);
       } catch (IllegalStateException e) {
         throw new NoSuchResourceException(e.getMessage());
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/885761f4/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
index dea37eb..c29a423 100644
--- 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
@@ -14,79 +14,24 @@
 
 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<EntityManager> entityManagerProvider;
+public class AmbariConfigurationDAO extends CrudDAO<AmbariConfigurationEntity, Long> {
 
-  /**
-   * 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);
+  public AmbariConfigurationDAO() {
+    super(AmbariConfigurationEntity.class);
   }
 
-  @RequiresSession
-  public List<AmbariConfigurationEntity> findAll() {
-    TypedQuery<AmbariConfigurationEntity> query = entityManagerProvider.get().createNamedQuery(
-      "AmbariConfigurationEntity.findAll", AmbariConfigurationEntity.class);
-    return daoUtils.selectList(query);
+  public void create(AmbariConfigurationEntity entity) {
+    super.create(entity);
   }
-
-
-  @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/885761f4/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/DaoUtils.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/DaoUtils.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/DaoUtils.java
index cd3faf0..e6112ad 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/DaoUtils.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/DaoUtils.java
@@ -18,8 +18,6 @@
 
 package org.apache.ambari.server.orm.dao;
 
-import static org.apache.ambari.server.orm.DBAccessor.DbType;
-
 import java.util.Collections;
 import java.util.List;
 
@@ -31,19 +29,10 @@ import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Root;
 
-import org.apache.ambari.server.orm.DBAccessor;
-
-import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
 @Singleton
 public class DaoUtils {
-  @Inject
-  private DBAccessor dbAccessor;
-
-  public DbType getDbType() {
-    return dbAccessor.getDbType();
-  }
 
   public <T> List<T> selectAll(EntityManager entityManager, Class<T> entityClass) {
     CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
@@ -92,7 +81,7 @@ public class DaoUtils {
 
   public void setParameters(Query query, Object... parameters) {
     for (int i = 0; i < parameters.length; i++) {
-      query.setParameter(i+1, parameters[i]);
+      query.setParameter(i + 1, parameters[i]);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/885761f4/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
index 74fff6c..5978c68 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -84,6 +84,23 @@ CREATE TABLE clusterconfig (
   CONSTRAINT UQ_config_type_tag UNIQUE (version_tag, type_name, cluster_id),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 
+CREATE TABLE configuration_base (
+  id BIGINT NOT NULL,
+  version_tag VARCHAR(255) NOT NULL,
+  version BIGINT NOT NULL,
+  type VARCHAR(255) NOT NULL,
+  data VARCHAR(3000) NOT NULL,
+  attributes VARCHAR(3000),
+  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 serviceconfig (
   service_config_id BIGINT NOT NULL,
   cluster_id BIGINT NOT NULL,
@@ -1145,6 +1162,8 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value)
   union all
   select 'servicecomponent_version_id_seq', 0 FROM SYSIBM.SYSDUMMY1
   union all
+  select 'configuration_id_seq', 0 FROM SYSIBM.SYSDUMMY1
+  union all
   select 'hostcomponentdesiredstate_id_seq', 0 FROM SYSIBM.SYSDUMMY1;
 
 
@@ -1245,6 +1264,7 @@ INSERT INTO roleauthorization(authorization_id, authorization_name)
   SELECT 'AMBARI.ADD_DELETE_CLUSTERS', 'Create new clusters' FROM SYSIBM.SYSDUMMY1 UNION ALL
   SELECT 'AMBARI.RENAME_CLUSTER', 'Rename clusters' FROM SYSIBM.SYSDUMMY1 UNION ALL
   SELECT 'AMBARI.MANAGE_SETTINGS', 'Manage settings' FROM SYSIBM.SYSDUMMY1 UNION ALL
+  SELECT 'AMBARI.MANAGE_CONFIGURATION', 'Manage ambari configurations' FROM SYSIBM.SYSDUMMY1 UNION ALL
   SELECT 'AMBARI.MANAGE_USERS', 'Manage users' FROM SYSIBM.SYSDUMMY1 UNION ALL
   SELECT 'AMBARI.MANAGE_GROUPS', 'Manage groups' FROM SYSIBM.SYSDUMMY1 UNION ALL
   SELECT 'AMBARI.MANAGE_VIEWS', 'Manage Ambari Views' FROM SYSIBM.SYSDUMMY1 UNION ALL
@@ -1446,6 +1466,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/885761f4/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 beda848..fd5f650 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -104,6 +104,23 @@ CREATE TABLE clusterconfig (
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 
+CREATE TABLE configuration_base (
+  id BIGINT NOT NULL,
+  version_tag VARCHAR(100) NOT NULL,
+  version BIGINT NOT NULL,
+  type VARCHAR(100) NOT NULL,
+  data LONGTEXT NOT NULL,
+  attributes LONGTEXT,
+  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 serviceconfig (
   service_config_id BIGINT NOT NULL,
   cluster_id BIGINT NOT NULL,
@@ -1109,6 +1126,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
@@ -1193,6 +1211,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
@@ -1398,6 +1417,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/885761f4/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 4f27dfb..fd2b73d 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -84,6 +84,23 @@ CREATE TABLE clusterconfig (
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 
+CREATE TABLE configuration_base (
+  id NUMBER(19) NOT NULL,
+  version_tag VARCHAR(255) NOT NULL,
+  version NUMBER(19) NOT NULL,
+  type VARCHAR(255) NOT NULL,
+  data CLOB NOT NULL,
+  attributes CLOB,
+  create_timestamp NUMBER(19) NOT NULL,
+  CONSTRAINT PK_configuration_base PRIMARY KEY (id)
+);
+
+CREATE TABLE ambari_configuration (
+  id NUMBER(19) NOT NULL,
+  CONSTRAINT PK_ambari_configuration PRIMARY KEY (id),
+  CONSTRAINT FK_ambari_configuration_configuration_base FOREIGN KEY (id) REFERENCES configuration_base (id)
+);
+
 CREATE TABLE serviceconfig (
   service_config_id NUMBER(19) NOT NULL,
   cluster_id NUMBER(19) NOT NULL,
@@ -1088,6 +1105,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('ambari_oper
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('remote_cluster_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('remote_cluster_service_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponent_version_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('configuration_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('hostcomponentdesiredstate_id_seq', 0);
 
 INSERT INTO metainfo("metainfo_key", "metainfo_value") values ('version', '${ambariSchemaVersion}');
@@ -1191,6 +1209,7 @@ INSERT INTO roleauthorization(authorization_id, authorization_name)
   SELECT 'AMBARI.ADD_DELETE_CLUSTERS', 'Create new clusters' FROM dual UNION ALL
   SELECT 'AMBARI.RENAME_CLUSTER', 'Rename clusters' FROM dual UNION ALL
   SELECT 'AMBARI.MANAGE_SETTINGS', 'Manage settings' FROM dual UNION ALL
+  SELECT 'AMBARI.MANAGE_CONFIGURATION', 'Manage ambari configuration' FROM dual UNION ALL
   SELECT 'AMBARI.MANAGE_USERS', 'Manage users' FROM dual UNION ALL
   SELECT 'AMBARI.MANAGE_GROUPS', 'Manage groups' FROM dual UNION ALL
   SELECT 'AMBARI.MANAGE_VIEWS', 'Manage Ambari Views' FROM dual UNION ALL
@@ -1396,6 +1415,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/885761f4/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 8550c2b..a59b4e3 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -67,13 +67,13 @@ CREATE TABLE clusters (
 );
 
 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,
+  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)
 );
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/885761f4/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index 76d4441..9d6403a 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -83,6 +83,23 @@ CREATE TABLE clusterconfig (
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 
+CREATE TABLE configuration_base (
+  id NUMERIC(19) NOT NULL,
+  version_tag VARCHAR(255) NOT NULL,
+  version NUMERIC(19) NOT NULL,
+  type VARCHAR(255) NOT NULL,
+  data TEXT NOT NULL,
+  attributes TEXT,
+  create_timestamp NUMERIC(19) NOT NULL,
+  CONSTRAINT PK_configuration_base PRIMARY KEY (id)
+);
+
+CREATE TABLE ambari_configuration (
+  id NUMERIC(19) NOT NULL,
+  CONSTRAINT PK_ambari_configuration PRIMARY KEY (id),
+  CONSTRAINT FK_ambari_configuration_configuration_base FOREIGN KEY (id) REFERENCES configuration_base (id)
+);
+
 CREATE TABLE serviceconfig (
   service_config_id NUMERIC(19) NOT NULL,
   cluster_id NUMERIC(19) NOT NULL,
@@ -1087,6 +1104,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('remote_clus
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('remote_cluster_service_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponent_version_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('hostcomponentdesiredstate_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('configuration_id_seq', 0);
 
 insert into adminresourcetype (resource_type_id, resource_type_name)
   select 1, 'AMBARI'
@@ -1187,6 +1205,7 @@ insert into adminpermission(permission_id, permission_name, resource_type_id, pe
     SELECT 'AMBARI.ADD_DELETE_CLUSTERS', 'Create new clusters' UNION ALL
     SELECT 'AMBARI.RENAME_CLUSTER', 'Rename clusters' UNION ALL
     SELECT 'AMBARI.MANAGE_SETTINGS', 'Manage 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
@@ -1392,6 +1411,7 @@ insert into adminpermission(permission_id, permission_name, resource_type_id, pe
     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/885761f4/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index f54a232..a5a0b20 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -97,6 +97,23 @@ CREATE TABLE clusterconfig (
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 
+CREATE TABLE configuration_base (
+  id BIGINT NOT NULL,
+  version_tag VARCHAR(255) NOT NULL,
+  version BIGINT NOT NULL,
+  type VARCHAR(255) NOT NULL,
+  data VARCHAR(MAX) NOT NULL,
+  attributes VARCHAR(MAX),
+  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 serviceconfig (
   service_config_id BIGINT NOT NULL,
   cluster_id BIGINT NOT NULL,
@@ -1112,6 +1129,7 @@ BEGIN TRANSACTION
     ('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)
@@ -1200,6 +1218,7 @@ BEGIN TRANSACTION
     SELECT 'AMBARI.ADD_DELETE_CLUSTERS', 'Create new clusters' UNION ALL
     SELECT 'AMBARI.RENAME_CLUSTER', 'Rename clusters' UNION ALL
     SELECT 'AMBARI.MANAGE_SETTINGS', 'Manage 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
@@ -1405,6 +1424,7 @@ BEGIN TRANSACTION
     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


[13/38] ambari git commit: AMBARI-21922. Allow SERVER Type Alerts To Run For Any Service/Component - addendum: fix imports (amagyar)

Posted by lp...@apache.org.
AMBARI-21922. Allow SERVER Type Alerts To Run For Any Service/Component - addendum: fix imports (amagyar)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c6e19b76
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c6e19b76
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c6e19b76

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: c6e19b765e80ad7e22ec63cdd4e8004960683466
Parents: 4f6ef91
Author: Attila Magyar <am...@hortonworks.com>
Authored: Wed Sep 13 09:12:40 2017 +0200
Committer: Attila Magyar <am...@hortonworks.com>
Committed: Wed Sep 13 09:12:40 2017 +0200

----------------------------------------------------------------------
 .../ambari/server/state/services/AmbariServerAlertService.java   | 1 -
 .../org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java  | 4 ++--
 2 files changed, 2 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c6e19b76/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
index f5d811d..d3237a9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
@@ -30,7 +30,6 @@ import java.util.concurrent.TimeUnit;
 import org.apache.ambari.server.AmbariService;
 import org.apache.ambari.server.alerts.AlertRunnable;
 import org.apache.ambari.server.controller.RootServiceResponseFactory.Components;
-import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
 import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.state.Cluster;

http://git-wip-us.apache.org/repos/asf/ambari/blob/c6e19b76/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
index d9c7957..34d415b 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
@@ -49,8 +49,6 @@ import java.util.Set;
 
 import javax.persistence.EntityManager;
 
-import com.google.common.collect.Maps;
-import com.google.inject.AbstractModule;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
@@ -93,7 +91,9 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 
+import com.google.common.collect.Maps;
 import com.google.gson.Gson;
+import com.google.inject.AbstractModule;
 import com.google.inject.Binder;
 import com.google.inject.Guice;
 import com.google.inject.Injector;