You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by tb...@apache.org on 2014/09/19 20:25:25 UTC
git commit: AMBARI-7349 - Admin : LDAP Sync API to support sync events
Repository: ambari
Updated Branches:
refs/heads/trunk 21d784b68 -> 1f7dbd5df
AMBARI-7349 - Admin : LDAP Sync API to support sync events
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1f7dbd5d
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1f7dbd5d
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1f7dbd5d
Branch: refs/heads/trunk
Commit: 1f7dbd5df4b624a083cc8f8fe4141e6289ecf46e
Parents: 21d784b
Author: tbeerbower <tb...@hortonworks.com>
Authored: Thu Sep 18 22:12:45 2014 -0400
Committer: tbeerbower <tb...@hortonworks.com>
Committed: Fri Sep 19 14:25:08 2014 -0400
----------------------------------------------------------------------
.../LdapSyncEventResourceDefinition.java | 57 +++
.../resources/ResourceInstanceFactoryImpl.java | 4 +
.../api/services/LdapSyncEventService.java | 144 ++++++
.../internal/DefaultProviderModule.java | 2 +
.../internal/LdapSyncEventResourceProvider.java | 438 +++++++++++++++++++
.../ambari/server/controller/spi/Resource.java | 4 +-
.../orm/entities/LdapSyncEventEntity.java | 284 ++++++++++++
.../server/orm/entities/LdapSyncSpecEntity.java | 143 ++++++
.../LdapSyncEventResourceDefinitionTest.java | 49 +++
.../api/services/LdapSyncEventServiceTest.java | 97 ++++
.../LdapSyncEventResourceProviderTest.java | 114 +++++
.../orm/entities/LdapSyncEventEntityTest.java | 166 +++++++
.../orm/entities/LdapSyncSpecEntityTest.java | 95 ++++
13 files changed, 1596 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/ambari-server/src/main/java/org/apache/ambari/server/api/resources/LdapSyncEventResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/LdapSyncEventResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/LdapSyncEventResourceDefinition.java
new file mode 100644
index 0000000..554c688
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/LdapSyncEventResourceDefinition.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * LDAP sync event resource definition.
+ */
+public class LdapSyncEventResourceDefinition extends BaseResourceDefinition {
+
+ // ----- Constructors ------------------------------------------------------
+
+ /**
+ * Construct an event resource definition.
+ */
+ public LdapSyncEventResourceDefinition() {
+ super(Resource.Type.LdapSyncEvent);
+ }
+
+
+ // ----- ResourceDefinition ------------------------------------------------
+
+ @Override
+ public String getPluralName() {
+ return "ldap_sync_events";
+ }
+
+ @Override
+ public String getSingularName() {
+ return "ldap_sync_event";
+ }
+
+ @Override
+ public Set<SubResourceDefinition> getSubResourceDefinitions() {
+ return Collections.emptySet();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/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 f85c0ea..2676fd3 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
@@ -280,6 +280,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
resourceDefinition = new ClientConfigResourceDefinition();
break;
+ case LdapSyncEvent:
+ resourceDefinition = new LdapSyncEventResourceDefinition();
+ break;
+
default:
throw new IllegalArgumentException("Unsupported resource type: " + type);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/ambari-server/src/main/java/org/apache/ambari/server/api/services/LdapSyncEventService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/LdapSyncEventService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/LdapSyncEventService.java
new file mode 100644
index 0000000..bf4bcff
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/LdapSyncEventService.java
@@ -0,0 +1,144 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.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.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.Collections;
+
+/**
+ * Service responsible for ldap sync event resource requests.
+ */
+@Path("/ldap_sync_events/")
+public class LdapSyncEventService extends BaseService {
+ /**
+ * Handles: GET /ldap_sync_events/{eventId}
+ * Get a specific view.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param eventId event id
+ *
+ * @return view instance representation
+ */
+ @GET
+ @Path("{eventId}")
+ @Produces("text/plain")
+ public Response getEvent(@Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("eventId") String eventId) {
+
+ return handleRequest(headers, null, ui, Request.Type.GET, createEventResource(eventId));
+ }
+
+ /**
+ * Handles: GET /ldap_sync_events
+ * Get all events.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ *
+ * @return view collection resource representation
+ */
+ @GET
+ @Produces("text/plain")
+ public Response getEvents(@Context HttpHeaders headers, @Context UriInfo ui) {
+ return handleRequest(headers, null, ui, Request.Type.GET, createEventResource(null));
+ }
+
+ /**
+ * Handles: POST /ldap_sync_events/
+ * Create an event.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ *
+ * @return information regarding the created view
+ */
+ @POST
+ @Produces("text/plain")
+ public Response createEvent(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+ return handleRequest(headers, body, ui, Request.Type.POST, createEventResource(null));
+ }
+
+ /**
+ * Handles: PUT /ldap_sync_events/{eventId}
+ * Update a specific event.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param eventId event id
+ *
+ * @return information regarding the updated event
+ */
+ @PUT
+ @Path("{eventId}")
+ @Produces("text/plain")
+ public Response updateEvent(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("eventId") String eventId) {
+
+ return handleRequest(headers, body, ui, Request.Type.PUT, createEventResource(eventId));
+ }
+
+ /**
+ * Handles: DELETE /ldap_sync_events/{eventId}
+ * Delete a specific view.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param eventId event id
+ *
+ * @return information regarding the deleted event
+ */
+ @DELETE
+ @Path("{eventId}")
+ @Produces("text/plain")
+ public Response deleteEvent(@Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("eventId") String eventId) {
+
+ return handleRequest(headers, null, ui, Request.Type.DELETE, createEventResource(eventId));
+ }
+
+
+ // ----- helper methods ----------------------------------------------------
+
+ /**
+ * Create a view resource.
+ *
+ * @param eventId the event id
+ *
+ * @return an event resource instance
+ */
+ private ResourceInstance createEventResource(String eventId) {
+ return createResource(Resource.Type.LdapSyncEvent,
+ Collections.singletonMap(Resource.Type.LdapSyncEvent, eventId));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/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 1b5075a..99ac0f1 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
@@ -79,6 +79,8 @@ public class DefaultProviderModule extends AbstractProviderModule {
return new ViewPermissionResourceProvider();
case ClusterPrivilege:
return new ClusterPrivilegeResourceProvider();
+ case LdapSyncEvent:
+ return new LdapSyncEventResourceProvider();
default:
return AbstractControllerResourceProvider.getResourceProvider(type, propertyIds,
keyPropertyIds, managementController);
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/LdapSyncEventResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/LdapSyncEventResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/LdapSyncEventResourceProvider.java
new file mode 100644
index 0000000..188c071
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/LdapSyncEventResourceProvider.java
@@ -0,0 +1,438 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.controller.internal;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.entities.LdapSyncEventEntity;
+import org.apache.ambari.server.orm.entities.LdapSyncSpecEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Resource provider for ldap sync events.
+ */
+public class LdapSyncEventResourceProvider extends AbstractResourceProvider {
+
+ /**
+ * Thread pool
+ */
+ private static ExecutorService executorService;
+
+ // TODO : Do we need to expose the thread pool params in configuration?
+ private final static int THREAD_POOL_CORE_SIZE = 2;
+ private final static int THREAD_POOL_MAX_SIZE = 5;
+ private final static long THREAD_POOL_TIMEOUT = 1000L;
+
+ /**
+ * Event property id constants.
+ */
+ public static final String EVENT_ID_PROPERTY_ID = "Event/id";
+ public static final String EVENT_STATUS_PROPERTY_ID = "Event/status";
+ public static final String EVENT_STATUS_DETAIL_PROPERTY_ID = "Event/status_detail";
+ public static final String EVENT_START_TIME_PROPERTY_ID = "Event/sync_start_time";
+ public static final String EVENT_END_TIME_PROPERTY_ID = "Event/sync_end_time";
+ public static final String USERS_FETCHED_PROPERTY_ID = "Event/results/users_fetched";
+ public static final String USERS_CREATED_PROPERTY_ID = "Event/results/users_created";
+ public static final String USERS_UPDATED_PROPERTY_ID = "Event/results/users_updated";
+ public static final String USERS_REMOVED_PROPERTY_ID = "Event/results/users_removed";
+ public static final String GROUPS_FETCHED_PROPERTY_ID = "Event/results/groups_fetched";
+ public static final String GROUPS_CREATED_PROPERTY_ID = "Event/results/groups_created";
+ public static final String GROUPS_UPDATED_PROPERTY_ID = "Event/results/groups_updated";
+ public static final String GROUPS_REMOVED_PROPERTY_ID = "Event/results/groups_removed";
+ public static final String MEMBERSHIPS_FETCHED_PROPERTY_ID = "Event/results/memberships_fetched";
+ public static final String MEMBERSHIPS_CREATED_PROPERTY_ID = "Event/results/memberships_created";
+ public static final String MEMBERSHIPS_UPDATED_PROPERTY_ID = "Event/results/memberships_updated";
+ public static final String EVENT_SPECS_PROPERTY_ID = "Event/specs";
+
+ /**
+ * The key property ids for a event resource.
+ */
+ private static Map<Resource.Type, String> keyPropertyIds = new HashMap<Resource.Type, String>();
+ static {
+ keyPropertyIds.put(Resource.Type.LdapSyncEvent, EVENT_ID_PROPERTY_ID);
+ }
+
+ /**
+ * The property ids for a event resource.
+ */
+ private static Set<String> propertyIds = new HashSet<String>();
+
+ static {
+ propertyIds.add(EVENT_ID_PROPERTY_ID);
+ propertyIds.add(EVENT_STATUS_PROPERTY_ID);
+ propertyIds.add(EVENT_STATUS_DETAIL_PROPERTY_ID);
+ propertyIds.add(EVENT_START_TIME_PROPERTY_ID);
+ propertyIds.add(EVENT_END_TIME_PROPERTY_ID);
+ propertyIds.add(USERS_FETCHED_PROPERTY_ID);
+ propertyIds.add(USERS_CREATED_PROPERTY_ID);
+ propertyIds.add(USERS_UPDATED_PROPERTY_ID);
+ propertyIds.add(USERS_REMOVED_PROPERTY_ID);
+ propertyIds.add(GROUPS_FETCHED_PROPERTY_ID);
+ propertyIds.add(GROUPS_CREATED_PROPERTY_ID);
+ propertyIds.add(GROUPS_UPDATED_PROPERTY_ID);
+ propertyIds.add(GROUPS_REMOVED_PROPERTY_ID);
+ propertyIds.add(MEMBERSHIPS_FETCHED_PROPERTY_ID);
+ propertyIds.add(MEMBERSHIPS_CREATED_PROPERTY_ID);
+ propertyIds.add(MEMBERSHIPS_UPDATED_PROPERTY_ID);
+ propertyIds.add(EVENT_SPECS_PROPERTY_ID);
+ }
+
+ /**
+ * Spec property keys.
+ */
+ private static final String PRINCIPAL_TYPE_SPEC_KEY = "principal_type";
+ private static final String SYNC_TYPE_SPEC_KEY = "sync_type";
+ private static final String NAMES_SPEC_KEY = "names";
+
+ /**
+ * Map of all sync events.
+ */
+ private final Map<Long, LdapSyncEventEntity> events = new ConcurrentSkipListMap<Long, LdapSyncEventEntity>();
+
+ /**
+ * The queue of events to be processed.
+ */
+ private final Queue<LdapSyncEventEntity> eventQueue = new LinkedList<LdapSyncEventEntity>();
+
+ /**
+ * Indicates whether or not the events are currently being processed.
+ */
+ private volatile boolean processingEvents = false;
+
+ /**
+ * The next event id.
+ */
+ private AtomicLong nextEventId = new AtomicLong(1L);
+
+ /**
+ * The logger.
+ */
+ protected final static Logger LOG = LoggerFactory.getLogger(LdapSyncEventResourceProvider.class);
+
+
+ // ----- Constructors ------------------------------------------------------
+
+ /**
+ * Construct a event resource provider.
+ */
+ public LdapSyncEventResourceProvider() {
+ super(propertyIds, keyPropertyIds);
+ }
+
+
+ // ----- ResourceProvider --------------------------------------------------
+
+ @Override
+ public RequestStatus createResources(Request event)
+ throws SystemException, UnsupportedPropertyException,
+ ResourceAlreadyExistsException, NoSuchParentResourceException {
+ Set<LdapSyncEventEntity> newEvents = new HashSet<LdapSyncEventEntity>();
+
+ for (Map<String, Object> properties : event.getProperties()) {
+ newEvents.add(createResources(getCreateCommand(properties)));
+ }
+ notifyCreate(Resource.Type.ViewInstance, event);
+
+ Set<Resource> associatedResources = new HashSet<Resource>();
+ for (LdapSyncEventEntity eventEntity : newEvents) {
+ Resource resource = new ResourceImpl(Resource.Type.LdapSyncEvent);
+ resource.setProperty(EVENT_ID_PROPERTY_ID, eventEntity.getId());
+ associatedResources.add(resource);
+ synchronized (eventQueue) {
+ eventQueue.offer(eventEntity);
+ }
+ }
+
+ ensureEventProcessor();
+
+ return getRequestStatus(null, associatedResources);
+ }
+
+ @Override
+ public Set<Resource> getResources(Request event, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+ Set<Resource> resources = new HashSet<Resource>();
+ Set<String> requestedIds = getRequestPropertyIds(event, predicate);
+
+ for (LdapSyncEventEntity eventEntity : events.values()) {
+ resources.add(toResource(eventEntity, requestedIds));
+ }
+ return resources;
+ }
+
+ @Override
+ public RequestStatus updateResources(Request event, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public RequestStatus deleteResources(Predicate predicate)
+ throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+ modifyResources(getDeleteCommand(predicate));
+ notifyDelete(Resource.Type.ViewInstance, predicate);
+ return getRequestStatus(null);
+ }
+
+ @Override
+ public Map<Resource.Type, String> getKeyPropertyIds() {
+ return keyPropertyIds;
+ }
+
+
+ // ----- AbstractResourceProvider ------------------------------------------
+
+ @Override
+ protected Set<String> getPKPropertyIds() {
+ return new HashSet<String>(keyPropertyIds.values());
+ }
+
+
+ // ----- helper methods ----------------------------------------------------
+
+ /**
+ * Ensure that sync events are being processed.
+ */
+ protected void ensureEventProcessor() {
+
+ if (!processingEvents) {
+ synchronized (eventQueue) {
+ if (!processingEvents) {
+ processingEvents = true;
+ getExecutorService().submit(new Runnable() {
+ @Override
+ public void run() {
+ processSyncEvents();
+ }
+ });
+ }
+ }
+ }
+ }
+
+ // create a resource from the given event entity
+ private Resource toResource(LdapSyncEventEntity eventEntity, Set<String> requestedIds) {
+ Resource resource = new ResourceImpl(Resource.Type.LdapSyncEvent);
+
+ setResourceProperty(resource, EVENT_ID_PROPERTY_ID, eventEntity.getId(), requestedIds);
+ setResourceProperty(resource, EVENT_STATUS_PROPERTY_ID, eventEntity.getStatus().toString().toUpperCase(), requestedIds);
+ setResourceProperty(resource, EVENT_STATUS_DETAIL_PROPERTY_ID, eventEntity.getStatusDetail(), requestedIds);
+ setResourceProperty(resource, USERS_FETCHED_PROPERTY_ID, eventEntity.getUsersFetched(), requestedIds);
+ setResourceProperty(resource, USERS_CREATED_PROPERTY_ID, eventEntity.getUsersCreated(), requestedIds);
+ setResourceProperty(resource, USERS_UPDATED_PROPERTY_ID, eventEntity.getUsersUpdated(), requestedIds);
+ setResourceProperty(resource, USERS_REMOVED_PROPERTY_ID, eventEntity.getUsersRemoved(), requestedIds);
+ setResourceProperty(resource, GROUPS_FETCHED_PROPERTY_ID, eventEntity.getGroupsFetched(), requestedIds);
+ setResourceProperty(resource, GROUPS_CREATED_PROPERTY_ID, eventEntity.getGroupsCreated(), requestedIds);
+ setResourceProperty(resource, GROUPS_UPDATED_PROPERTY_ID, eventEntity.getGroupsUpdated(), requestedIds);
+ setResourceProperty(resource, GROUPS_REMOVED_PROPERTY_ID, eventEntity.getGroupsRemoved(), requestedIds);
+ setResourceProperty(resource, MEMBERSHIPS_FETCHED_PROPERTY_ID, eventEntity.getMembershipsFetched(), requestedIds);
+ setResourceProperty(resource, MEMBERSHIPS_CREATED_PROPERTY_ID, eventEntity.getMembershipsCreated(), requestedIds);
+ setResourceProperty(resource, MEMBERSHIPS_UPDATED_PROPERTY_ID, eventEntity.getMembershipsUpdated(), requestedIds);
+
+ Set<Map<String, String>> specs = new HashSet<Map<String, String>>();
+
+ List<LdapSyncSpecEntity> specList = eventEntity.getSpecs();
+
+ for (LdapSyncSpecEntity spec : specList) {
+
+ Map<String, String> specMap = new HashMap<String, String>();
+
+ specMap.put(PRINCIPAL_TYPE_SPEC_KEY, spec.getPrincipalType().toString().toLowerCase());
+ specMap.put(SYNC_TYPE_SPEC_KEY, spec.getSyncType().toString().toLowerCase());
+
+ List<String> names = spec.getPrincipalNames();
+
+ if (!names.isEmpty()) {
+ specMap.put(NAMES_SPEC_KEY, names.toString().replace("[", "").replace("]", "").replace(", ", ","));
+ }
+ specs.add(specMap);
+ }
+ setResourceProperty(resource, EVENT_SPECS_PROPERTY_ID, specs, requestedIds);
+
+ setResourceProperty(resource, EVENT_START_TIME_PROPERTY_ID, eventEntity.getStartTime(), requestedIds);
+ setResourceProperty(resource, EVENT_END_TIME_PROPERTY_ID, eventEntity.getEndTime(), requestedIds);
+
+ return resource;
+ }
+
+ // create a event entity from the given set of properties
+ private LdapSyncEventEntity toEntity(Map<String, Object> properties) {
+ LdapSyncEventEntity entity = new LdapSyncEventEntity(getNextEventId());
+ List<LdapSyncSpecEntity> specList = new LinkedList<LdapSyncSpecEntity>();
+
+ Set<Map<String, String>> specs = (Set<Map<String, String>>) properties.get(EVENT_SPECS_PROPERTY_ID);
+
+ for (Map<String, String> specMap : specs) {
+
+ LdapSyncSpecEntity.SyncType syncType = null;
+ LdapSyncSpecEntity.PrincipalType principalType = null;
+
+ List<String> principalNames = Collections.emptyList();
+
+ for (Map.Entry<String, String> entry : specMap.entrySet()) {
+ String key = entry.getKey();
+ if (key.equalsIgnoreCase(PRINCIPAL_TYPE_SPEC_KEY)) {
+ principalType = LdapSyncSpecEntity.PrincipalType.valueOfIgnoreCase(entry.getValue());
+
+ } else if (key.equalsIgnoreCase(SYNC_TYPE_SPEC_KEY)) {
+ syncType = LdapSyncSpecEntity.SyncType.valueOfIgnoreCase(entry.getValue());
+
+ } else if (key.equalsIgnoreCase(NAMES_SPEC_KEY)) {
+ String names = entry.getValue();
+ principalNames = Arrays.asList(names.split("\\s*,\\s*"));
+ } else {
+ throw new IllegalArgumentException("Unknown spec key " + key + ".");
+ }
+ }
+
+ if (syncType == null || principalType == null) {
+ throw new IllegalArgumentException("LDAP event spec must include both sync-type and principal-type.");
+ }
+
+ LdapSyncSpecEntity spec = new LdapSyncSpecEntity(principalType, syncType, principalNames);
+ specList.add(spec);
+ }
+ entity.setSpecs(specList);
+
+ return entity;
+ }
+
+ // get the next event id
+ private long getNextEventId() {
+ return nextEventId.getAndIncrement();
+ }
+
+ // Create a create command with all properties set
+ private Command<LdapSyncEventEntity> getCreateCommand(final Map<String, Object> properties) {
+ return new Command<LdapSyncEventEntity>() {
+ @Override
+ public LdapSyncEventEntity invoke() throws AmbariException {
+
+ LdapSyncEventEntity eventEntity = toEntity(properties);
+
+ events.put(eventEntity.getId(), eventEntity);
+
+ return eventEntity;
+ }
+ };
+ }
+
+ // Create a delete command with the given predicate
+ private Command<Void> getDeleteCommand(final Predicate predicate) {
+ return new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ Set<String> requestedIds = getRequestPropertyIds(PropertyHelper.getReadRequest(), predicate);
+
+ Set<LdapSyncEventEntity> entities = new HashSet<LdapSyncEventEntity>();
+
+ for (LdapSyncEventEntity entity : events.values()){
+ Resource resource = toResource(entity, requestedIds);
+ if (predicate == null || predicate.evaluate(resource)) {
+ entities.add(entity);
+ }
+ }
+ for (LdapSyncEventEntity entity : entities) {
+ events.remove(entity.getId());
+ }
+ return null;
+ }
+ };
+ }
+
+ // Get the ldap sync thread pool
+ private static synchronized ExecutorService getExecutorService() {
+ if (executorService == null) {
+ LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
+
+ ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
+ THREAD_POOL_CORE_SIZE,
+ THREAD_POOL_MAX_SIZE,
+ THREAD_POOL_TIMEOUT,
+ TimeUnit.MILLISECONDS,
+ queue);
+
+ threadPoolExecutor.allowCoreThreadTimeOut(true);
+ executorService = threadPoolExecutor;
+ }
+ return executorService;
+ }
+
+ // Process any queued up sync events
+ private void processSyncEvents() {
+
+ while (processingEvents) {
+ LdapSyncEventEntity event;
+ synchronized (eventQueue) {
+ event = eventQueue.poll();
+ if (event == null) {
+ processingEvents = false;
+ return;
+ }
+ }
+
+ event.setStatus(LdapSyncEventEntity.Status.Running);
+ event.setStatusDetail("Running LDAP sync.");
+ event.setStartTime(System.currentTimeMillis());
+
+ try {
+
+ // TODO : call back end code to perform LDAP sync
+
+ // TODO : update event resource with results of sync
+
+ event.setEndTime(System.currentTimeMillis());
+ event.setStatus(LdapSyncEventEntity.Status.Complete);
+ event.setStatusDetail("Completed LDAP sync.");
+ } catch (Exception e) {
+ String msg = "Caught exception running LDAP sync. ";
+ event.setStatus(LdapSyncEventEntity.Status.Error);
+ event.setStatusDetail(msg + e.getMessage());
+ LOG.error(msg, e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/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 a14f1f0..6cf34ca 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
@@ -121,7 +121,8 @@ public interface Resource {
ViewPermission,
Controller,
ClientConfig,
- StackLevelConfiguration;
+ StackLevelConfiguration,
+ LdapSyncEvent;
/**
* Get the {@link Type} that corresponds to this InternalType.
@@ -204,6 +205,7 @@ public interface Resource {
public static final Type Controller = InternalType.Controller.getType();
public static final Type ClientConfig = InternalType.ClientConfig.getType();
public static final Type StackLevelConfiguration = InternalType.StackLevelConfiguration.getType();
+ public static final Type LdapSyncEvent = InternalType.LdapSyncEvent.getType();
/**
* The type name.
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/LdapSyncEventEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/LdapSyncEventEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/LdapSyncEventEntity.java
new file mode 100644
index 0000000..9ce3ee0
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/LdapSyncEventEntity.java
@@ -0,0 +1,284 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import java.util.List;
+
+/**
+ * LDAP sync event entity.
+ */
+public class LdapSyncEventEntity {
+
+ /**
+ * The unique id.
+ */
+ private final long id;
+
+ /**
+ * The status of this event.
+ */
+ private Status status;
+
+ /**
+ * The detail status message for this event.
+ */
+ private String statusDetail;
+
+ /**
+ * Sync event times.
+ */
+ private long startTime;
+ private long endTime;
+
+ /**
+ * Results of sync event.
+ */
+ private Integer usersFetched;
+ private Integer usersCreated;
+ private Integer usersUpdated;
+ private Integer usersRemoved;
+ private Integer groupsFetched;
+ private Integer groupsCreated;
+ private Integer groupsUpdated;
+ private Integer groupsRemoved;
+ private Integer membershipsFetched;
+ private Integer membershipsCreated;
+ private Integer membershipsUpdated;
+
+ /**
+ * The specifications that define the sync event.
+ */
+ private List<LdapSyncSpecEntity> specs;
+
+
+ // ----- Constructors ------------------------------------------------------
+
+ /**
+ * Construct an LdapSyncEventEntity.
+ *
+ * @param id the unique id
+ */
+ public LdapSyncEventEntity(long id) {
+ this.id = id;
+ this.status = Status.Pending;
+ }
+
+
+ // ----- LdapSyncEventEntity -----------------------------------------------
+
+ /**
+ * Get the id.
+ *
+ * @return the id
+ */
+ public long getId() {
+ return id;
+ }
+
+ /**
+ * Get the event status.
+ *
+ * @return the status
+ */
+ public Status getStatus() {
+ return status;
+ }
+
+ /**
+ * Set the event status.
+ *
+ * @param status the status
+ */
+ public void setStatus(Status status) {
+ this.status = status;
+ }
+
+ /**
+ * Get the event status detail message.
+ *
+ * @return the event detail
+ */
+ public String getStatusDetail() {
+ return statusDetail;
+ }
+
+ /**
+ * Set the event status detail message.
+ *
+ * @param statusDetail the event status detail message
+ */
+ public void setStatusDetail(String statusDetail) {
+ this.statusDetail = statusDetail;
+ }
+
+ /**
+ * Get the event specifications.
+ *
+ * @return the event specs
+ */
+ public List<LdapSyncSpecEntity> getSpecs() {
+ return specs;
+ }
+
+ /**
+ * Set the event specifications.
+ *
+ * @param specs the event specifications
+ */
+ public void setSpecs(List<LdapSyncSpecEntity> specs) {
+ this.specs = specs;
+ }
+
+ /**
+ * Get the time that the sync started.
+ *
+ * @return the sync start time (millis)
+ */
+ public long getStartTime() {
+ return startTime;
+ }
+
+ /**
+ * Set the sync start time.
+ *
+ * @param startTime the sync start time (millis)
+ */
+ public void setStartTime(long startTime) {
+ this.startTime = startTime;
+ }
+
+ /**
+ * Get the time the the sync event ended.
+ *
+ * @return the end time (millis)
+ */
+ public long getEndTime() {
+ return endTime;
+ }
+
+ /**
+ * Set the sync end time.
+ *
+ * @param endTime the end time (millis)
+ */
+ public void setEndTime(long endTime) {
+ this.endTime = endTime;
+ }
+
+ public Integer getUsersFetched() {
+ return usersFetched;
+ }
+
+ public void setUsersFetched(Integer usersFetched) {
+ this.usersFetched = usersFetched;
+ }
+
+ public Integer getUsersCreated() {
+ return usersCreated;
+ }
+
+ public void setUsersCreated(Integer usersCreated) {
+ this.usersCreated = usersCreated;
+ }
+
+ public Integer getUsersUpdated() {
+ return usersUpdated;
+ }
+
+ public void setUsersUpdated(Integer usersUpdated) {
+ this.usersUpdated = usersUpdated;
+ }
+
+ public Integer getUsersRemoved() {
+ return usersRemoved;
+ }
+
+ public void setUsersRemoved(Integer usersRemoved) {
+ this.usersRemoved = usersRemoved;
+ }
+
+ public Integer getGroupsFetched() {
+ return groupsFetched;
+ }
+
+ public void setGroupsFetched(Integer groupsFetched) {
+ this.groupsFetched = groupsFetched;
+ }
+
+ public Integer getGroupsCreated() {
+ return groupsCreated;
+ }
+
+ public void setGroupsCreated(Integer groupsCreated) {
+ this.groupsCreated = groupsCreated;
+ }
+
+ public Integer getGroupsUpdated() {
+ return groupsUpdated;
+ }
+
+ public void setGroupsUpdated(Integer groupsUpdated) {
+ this.groupsUpdated = groupsUpdated;
+ }
+
+ public Integer getGroupsRemoved() {
+ return groupsRemoved;
+ }
+
+ public void setGroupsRemoved(Integer groupsRemoved) {
+ this.groupsRemoved = groupsRemoved;
+ }
+
+ public Integer getMembershipsFetched() {
+ return membershipsFetched;
+ }
+
+ public void setMembershipsFetched(Integer membershipsFetched) {
+ this.membershipsFetched = membershipsFetched;
+ }
+
+ public Integer getMembershipsCreated() {
+ return membershipsCreated;
+ }
+
+ public void setMembershipsCreated(Integer membershipsCreated) {
+ this.membershipsCreated = membershipsCreated;
+ }
+
+ public Integer getMembershipsUpdated() {
+ return membershipsUpdated;
+ }
+
+ public void setMembershipsUpdated(Integer membershipsUpdated) {
+ this.membershipsUpdated = membershipsUpdated;
+ }
+
+
+ // ----- enum : Status -----------------------------------------------------
+
+ /**
+ * LDAP sync event status
+ */
+ public enum Status {
+ Pending,
+ Running,
+ Error,
+ Complete
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/LdapSyncSpecEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/LdapSyncSpecEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/LdapSyncSpecEntity.java
new file mode 100644
index 0000000..027a4ce
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/LdapSyncSpecEntity.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import java.util.List;
+
+/**
+ * LDAP sync specification entity.
+ */
+public class LdapSyncSpecEntity {
+
+ /**
+ * The principal type.
+ */
+ private PrincipalType principalType;
+
+ /**
+ * The sync type.
+ */
+ private SyncType syncType;
+
+ /**
+ * The list of principal names.
+ */
+ private List<String> principalNames;
+
+
+ // ----- Constructors ------------------------------------------------------
+
+ /**
+ * Construct an LdapSyncSpecEntity.
+ *
+ * @param principalType the principal type
+ * @param syncType the sync type
+ * @param principalNames the list of principal names.
+ */
+ public LdapSyncSpecEntity(PrincipalType principalType, SyncType syncType, List<String> principalNames) {
+ this.principalType = principalType;
+ this.syncType = syncType;
+ this.principalNames = principalNames;
+
+ if (syncType == SyncType.Specific) {
+ if (principalNames.isEmpty()) {
+ throw new IllegalArgumentException("Missing principal names for " + syncType + " sync-type.");
+ }
+ } else {
+ if (!principalNames.isEmpty()) {
+ throw new IllegalArgumentException("Principal names should not be specified for " + syncType + " sync-type.");
+ }
+ }
+ }
+
+
+ // ----- LdapSyncSpecEntity ------------------------------------------------
+
+ /**
+ * Get the principal type.
+ *
+ * @return the principal type
+ */
+ public PrincipalType getPrincipalType() {
+ return principalType;
+ }
+
+ /**
+ * Get the sync type.
+ *
+ * @return the sync type
+ */
+ public SyncType getSyncType() {
+ return syncType;
+ }
+
+ /**
+ * Get a list of principal names.
+ *
+ * @return the list of principal names.
+ */
+ public List<String> getPrincipalNames() {
+ return principalNames;
+ }
+
+
+ // ----- enum : PrincipalType ----------------------------------------------
+
+ /**
+ * LDAP sync principal type.
+ */
+ public enum PrincipalType {
+ Users,
+ Groups;
+
+ /**
+ * Get the enum value for the given principal type name string, ignoring case.
+ *
+ * @param type the principal type name
+ *
+ * @return the enum value for the given type name
+ */
+ public static PrincipalType valueOfIgnoreCase(String type) {
+ return valueOf(Character.toUpperCase(type.charAt(0)) + type.substring(1).toLowerCase());
+ }
+ }
+
+
+ // ----- enum : SyncType ---------------------------------------------------
+
+ /**
+ * LDAP sync type.
+ */
+ public enum SyncType {
+ All,
+ Existing,
+ Specific;
+
+ /**
+ * Get the enum value for the given sync type name string, ignoring case.
+ *
+ * @param type the sync type name
+ *
+ * @return the enum value for the given type name
+ */
+ public static SyncType valueOfIgnoreCase(String type) {
+ return valueOf(Character.toUpperCase(type.charAt(0)) + type.substring(1).toLowerCase());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/ambari-server/src/test/java/org/apache/ambari/server/api/resources/LdapSyncEventResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/LdapSyncEventResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/LdapSyncEventResourceDefinitionTest.java
new file mode 100644
index 0000000..a0a3b60
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/LdapSyncEventResourceDefinitionTest.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.resources;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Set;
+
+/**
+ * LdapSyncEventResourceDefinition tests.
+ */
+public class LdapSyncEventResourceDefinitionTest {
+ @Test
+ public void testGetPluralName() throws Exception {
+ LdapSyncEventResourceDefinition resourceDefinition = new LdapSyncEventResourceDefinition();
+ Assert.assertEquals("ldap_sync_events", resourceDefinition.getPluralName());
+ }
+
+ @Test
+ public void testGetSingularName() throws Exception {
+ LdapSyncEventResourceDefinition resourceDefinition = new LdapSyncEventResourceDefinition();
+ Assert.assertEquals("ldap_sync_event", resourceDefinition.getSingularName());
+ }
+
+ @Test
+ public void testGetSubResourceDefinitions() throws Exception {
+ LdapSyncEventResourceDefinition resourceDefinition = new LdapSyncEventResourceDefinition();
+ Set<SubResourceDefinition> subResourceDefinitions = resourceDefinition.getSubResourceDefinitions ();
+
+ Assert.assertEquals(0, subResourceDefinitions.size());
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/ambari-server/src/test/java/org/apache/ambari/server/api/services/LdapSyncEventServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/LdapSyncEventServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/LdapSyncEventServiceTest.java
new file mode 100644
index 0000000..af458b2
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/LdapSyncEventServiceTest.java
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.parsers.RequestBodyParser;
+import org.apache.ambari.server.api.services.serializers.ResultSerializer;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * LdapSyncEventService tests.
+ */
+public class LdapSyncEventServiceTest extends BaseServiceTest {
+
+ public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+ List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+ //getEvent
+ LdapSyncEventService permissionService = new TestLdapSyncEventService();
+ Method m = permissionService.getClass().getMethod("getEvent", HttpHeaders.class, UriInfo.class, String.class);
+ Object[] args = new Object[] {getHttpHeaders(), getUriInfo(), "1"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, permissionService, m, args, null));
+
+ //getEvents
+ permissionService = new TestLdapSyncEventService();
+ m = permissionService.getClass().getMethod("getEvents", HttpHeaders.class, UriInfo.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo()};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, permissionService, m, args, null));
+
+ //createEvent
+ permissionService = new TestLdapSyncEventService();
+ m = permissionService.getClass().getMethod("createEvent", String.class, HttpHeaders.class, UriInfo.class);
+ args = new Object[] {"body", getHttpHeaders(), getUriInfo()};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.POST, permissionService, m, args, "body"));
+
+ //deleteEvent
+ permissionService = new TestLdapSyncEventService();
+ m = permissionService.getClass().getMethod("deleteEvent", HttpHeaders.class, UriInfo.class, String.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo(), "1"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.DELETE, permissionService, m, args, null));
+
+ return listInvocations;
+ }
+
+
+ private class TestLdapSyncEventService extends LdapSyncEventService {
+
+ private TestLdapSyncEventService() {
+ super();
+ }
+
+ @Override
+ protected ResourceInstance createResource(Resource.Type type, Map<Resource.Type, String> mapIds) {
+ return getTestResource();
+ }
+
+ @Override
+ RequestFactory getRequestFactory() {
+ return getTestRequestFactory();
+ }
+
+ @Override
+ protected RequestBodyParser getBodyParser() {
+ return getTestBodyParser();
+ }
+
+ @Override
+ protected ResultSerializer getResultSerializer() {
+ return getTestResultSerializer();
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/LdapSyncEventResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/LdapSyncEventResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/LdapSyncEventResourceProviderTest.java
new file mode 100644
index 0000000..92bd7a4
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/LdapSyncEventResourceProviderTest.java
@@ -0,0 +1,114 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.controller.internal;
+
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.easymock.EasyMock.createNiceMock;
+
+/**
+ * LdapSyncEventResourceProvider tests.
+ */
+public class LdapSyncEventResourceProviderTest {
+ @Test
+ public void testCreateResources() throws Exception {
+ LdapSyncEventResourceProvider provider = new TestLdapSyncEventResourceProvider();
+
+ Set<Map<String, Object>> properties = new HashSet<Map<String, Object>>();
+ Map<String, Object> propertyMap = new HashMap<String, Object>();
+
+ Set<Map<String, String>> specs = new HashSet<Map<String, String>>();
+
+ propertyMap.put(LdapSyncEventResourceProvider.EVENT_SPECS_PROPERTY_ID, specs);
+ properties.add(propertyMap);
+
+ provider.createResources(PropertyHelper.getCreateRequest(properties, null));
+ }
+
+ @Test
+ public void testGetResources() throws Exception {
+ LdapSyncEventResourceProvider provider = new TestLdapSyncEventResourceProvider();
+
+ Set<Map<String, Object>> properties = new HashSet<Map<String, Object>>();
+ Map<String, Object> propertyMap = new HashMap<String, Object>();
+
+ Set<Map<String, String>> specs = new HashSet<Map<String, String>>();
+
+ propertyMap.put(LdapSyncEventResourceProvider.EVENT_SPECS_PROPERTY_ID, specs);
+ properties.add(propertyMap);
+
+ provider.createResources(PropertyHelper.getCreateRequest(properties, null));
+
+ Set<Resource> resources = provider.getResources(PropertyHelper.getReadRequest(), null);
+ Assert.assertEquals(1, resources.size());
+ }
+
+ @Test
+ public void testUpdateResources() throws Exception {
+ LdapSyncEventResourceProvider provider = new TestLdapSyncEventResourceProvider();
+
+ Request request = createNiceMock(Request.class);
+
+ try {
+ provider.updateResources(request, null);
+ Assert.fail("expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testDeleteResources() throws Exception {
+ LdapSyncEventResourceProvider provider = new TestLdapSyncEventResourceProvider();
+
+ Set<Map<String, Object>> properties = new HashSet<Map<String, Object>>();
+ Map<String, Object> propertyMap = new HashMap<String, Object>();
+
+ Set<Map<String, String>> specs = new HashSet<Map<String, String>>();
+
+ propertyMap.put(LdapSyncEventResourceProvider.EVENT_SPECS_PROPERTY_ID, specs);
+ properties.add(propertyMap);
+
+ provider.createResources(PropertyHelper.getCreateRequest(properties, null));
+
+ Set<Resource> resources = provider.getResources(PropertyHelper.getReadRequest(), null);
+ Assert.assertEquals(1, resources.size());
+
+ provider.deleteResources(null);
+
+ resources = provider.getResources(PropertyHelper.getReadRequest(), null);
+ Assert.assertEquals(0, resources.size());
+ }
+
+
+ protected static class TestLdapSyncEventResourceProvider extends LdapSyncEventResourceProvider {
+ @Override
+ protected void ensureEventProcessor() {
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/LdapSyncEventEntityTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/LdapSyncEventEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/LdapSyncEventEntityTest.java
new file mode 100644
index 0000000..66f9d6d
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/LdapSyncEventEntityTest.java
@@ -0,0 +1,166 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * LdapSyncEventEntity tests.
+ */
+public class LdapSyncEventEntityTest {
+ @Test
+ public void testGetId() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ Assert.assertEquals(1L, event.getId());
+ }
+
+ @Test
+ public void testSetGetStatus() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ Assert.assertEquals(LdapSyncEventEntity.Status.Pending, event.getStatus());
+
+ event.setStatus(LdapSyncEventEntity.Status.Running);
+ Assert.assertEquals(LdapSyncEventEntity.Status.Running, event.getStatus());
+
+ event.setStatus(LdapSyncEventEntity.Status.Complete);
+ Assert.assertEquals(LdapSyncEventEntity.Status.Complete, event.getStatus());
+
+ event.setStatus(LdapSyncEventEntity.Status.Error);
+ Assert.assertEquals(LdapSyncEventEntity.Status.Error, event.getStatus());
+
+ event.setStatus(LdapSyncEventEntity.Status.Pending);
+ Assert.assertEquals(LdapSyncEventEntity.Status.Pending, event.getStatus());
+ }
+
+ @Test
+ public void testSetGetStatusDetail() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setStatusDetail("some detail");
+ Assert.assertEquals("some detail", event.getStatusDetail());
+ }
+
+ @Test
+ public void testSetGetSpecs() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ LdapSyncSpecEntity spec = new LdapSyncSpecEntity(LdapSyncSpecEntity.PrincipalType.Groups,
+ LdapSyncSpecEntity.SyncType.All, Collections.<String>emptyList());
+
+ event.setSpecs(Collections.singletonList(spec));
+
+ List<LdapSyncSpecEntity> specs = event.getSpecs();
+ Assert.assertEquals(1, specs.size());
+
+ Assert.assertEquals(spec, specs.get(0));
+ }
+
+ @Test
+ public void testSetGetStartTime() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setStartTime(10001000L);
+ Assert.assertEquals(10001000L, event.getStartTime());
+ }
+
+ @Test
+ public void testSetGetEndTime() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setEndTime(90009000L);
+ Assert.assertEquals(90009000L, event.getEndTime());
+ }
+
+ @Test
+ public void testSetGetUsersFetched() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setUsersFetched(99);
+ Assert.assertEquals(Integer.valueOf(99), event.getUsersFetched());
+ }
+
+ @Test
+ public void testSetGetUsersCreated() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setUsersCreated(98);
+ Assert.assertEquals(Integer.valueOf(98), event.getUsersCreated());
+ }
+
+ @Test
+ public void testSetGetUsersUpdated() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setUsersUpdated(97);
+ Assert.assertEquals(Integer.valueOf(97), event.getUsersUpdated());
+ }
+
+ @Test
+ public void testSetGetUsersRemoved() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setUsersRemoved(96);
+ Assert.assertEquals(Integer.valueOf(96), event.getUsersRemoved());
+ }
+
+ @Test
+ public void testSetGetGroupsFetched() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setGroupsFetched(95);
+ Assert.assertEquals(Integer.valueOf(95), event.getGroupsFetched());
+ }
+
+ @Test
+ public void testSetGetGroupsCreated() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setGroupsCreated(94);
+ Assert.assertEquals(Integer.valueOf(94), event.getGroupsCreated());
+ }
+
+ @Test
+ public void testSetGetGroupsUpdated() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setGroupsUpdated(93);
+ Assert.assertEquals(Integer.valueOf(93), event.getGroupsUpdated());
+ }
+
+ @Test
+ public void testSetGetGroupsRemoved() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setGroupsRemoved(92);
+ Assert.assertEquals(Integer.valueOf(92), event.getGroupsRemoved());
+ }
+
+ @Test
+ public void testSetGetMembershipsFetched() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setMembershipsFetched(91);
+ Assert.assertEquals(Integer.valueOf(91), event.getMembershipsFetched());
+ }
+
+ @Test
+ public void testSetGetMembershipsCreated() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setMembershipsCreated(90);
+ Assert.assertEquals(Integer.valueOf(90), event.getMembershipsCreated());
+ }
+
+ @Test
+ public void testSetGetMembershipsUpdated() throws Exception {
+ LdapSyncEventEntity event = new LdapSyncEventEntity(1L);
+ event.setMembershipsUpdated(99);
+ Assert.assertEquals(Integer.valueOf(99), event.getMembershipsUpdated());
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7dbd5d/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/LdapSyncSpecEntityTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/LdapSyncSpecEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/LdapSyncSpecEntityTest.java
new file mode 100644
index 0000000..468281f
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/LdapSyncSpecEntityTest.java
@@ -0,0 +1,95 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * LdapSyncSpecEntity tests.
+ */
+public class LdapSyncSpecEntityTest {
+ @Test
+ public void testGetPrincipalType() throws Exception {
+ LdapSyncSpecEntity entity = new LdapSyncSpecEntity(LdapSyncSpecEntity.PrincipalType.Users,
+ LdapSyncSpecEntity.SyncType.All, Collections.<String>emptyList());
+ Assert.assertEquals(LdapSyncSpecEntity.PrincipalType.Users, entity.getPrincipalType());
+
+ entity = new LdapSyncSpecEntity(LdapSyncSpecEntity.PrincipalType.Groups,
+ LdapSyncSpecEntity.SyncType.All, Collections.<String>emptyList());
+ Assert.assertEquals(LdapSyncSpecEntity.PrincipalType.Groups, entity.getPrincipalType());
+ }
+
+ @Test
+ public void testGetSyncType() throws Exception {
+ LdapSyncSpecEntity entity = new LdapSyncSpecEntity(LdapSyncSpecEntity.PrincipalType.Users,
+ LdapSyncSpecEntity.SyncType.All, Collections.<String>emptyList());
+ Assert.assertEquals(LdapSyncSpecEntity.SyncType.All, entity.getSyncType());
+
+ entity = new LdapSyncSpecEntity(LdapSyncSpecEntity.PrincipalType.Users,
+ LdapSyncSpecEntity.SyncType.Existing, Collections.<String>emptyList());
+ Assert.assertEquals(LdapSyncSpecEntity.SyncType.Existing, entity.getSyncType());
+ }
+
+ @Test
+ public void testGetPrincipalNames() throws Exception {
+ List<String> names = new LinkedList<String>();
+ names.add("joe");
+ names.add("fred");
+
+ LdapSyncSpecEntity entity = new LdapSyncSpecEntity(LdapSyncSpecEntity.PrincipalType.Users,
+ LdapSyncSpecEntity.SyncType.Specific, names);
+ Assert.assertEquals(names, entity.getPrincipalNames());
+ }
+
+ @Test
+ public void testIllegalConstruction() throws Exception {
+ try {
+ new LdapSyncSpecEntity(LdapSyncSpecEntity.PrincipalType.Users,
+ LdapSyncSpecEntity.SyncType.Specific, Collections.<String>emptyList());
+ Assert.fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ List<String> names = new LinkedList<String>();
+ names.add("joe");
+ names.add("fred");
+
+ try {
+ new LdapSyncSpecEntity(LdapSyncSpecEntity.PrincipalType.Users,
+ LdapSyncSpecEntity.SyncType.All, names);
+ Assert.fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ new LdapSyncSpecEntity(LdapSyncSpecEntity.PrincipalType.Users,
+ LdapSyncSpecEntity.SyncType.Existing, names);
+ Assert.fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}