You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2016/06/15 13:10:24 UTC

ambari git commit: AMBARI-17224. Add ability to set GET request directives (rlevas)

Repository: ambari
Updated Branches:
  refs/heads/trunk 2bb19e9fa -> 91be58862


AMBARI-17224. Add ability to set GET request directives (rlevas)


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

Branch: refs/heads/trunk
Commit: 91be58862583047d74604f440d85a9fe64914169
Parents: 2bb19e9
Author: Robert Levas <rl...@hortonworks.com>
Authored: Wed Jun 15 09:10:14 2016 -0400
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Wed Jun 15 09:10:19 2016 -0400

----------------------------------------------------------------------
 .../ambari/server/api/handlers/ReadHandler.java |  8 ++
 .../apache/ambari/server/api/query/Query.java   | 17 +++++
 .../ambari/server/api/query/QueryImpl.java      | 20 ++++-
 .../api/resources/BaseResourceDefinition.java   | 80 ++++++++++++++------
 .../api/resources/ResourceDefinition.java       |  9 +++
 .../api/resources/SimpleResourceDefinition.java | 36 ++++-----
 .../resources/UpgradeResourceDefinition.java    |  7 +-
 .../ambari/server/api/services/BaseRequest.java |  3 +
 .../server/api/services/RequestFactory.java     | 18 ++++-
 .../server/api/handlers/ReadHandlerTest.java    | 18 ++++-
 .../resources/BaseResourceDefinitionTest.java   | 23 ++++--
 .../resources/SimpleResourceDefinitionTest.java | 45 +++++++++--
 .../server/api/services/RequestFactoryTest.java | 38 ++++++++++
 .../creator/AuditEventCreatorTestHelper.java    |  5 ++
 14 files changed, 265 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java
index 95e45d6..a93951e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java
@@ -19,6 +19,7 @@
 package org.apache.ambari.server.api.handlers;
 
 import org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.api.services.RequestBody;
 import org.apache.ambari.server.api.services.ResultImpl;
 import org.apache.ambari.server.api.services.ResultStatus;
 import org.apache.ambari.server.api.services.Result;
@@ -54,6 +55,13 @@ public class ReadHandler implements RequestHandler {
     query.setSortRequest(request.getSortRequest());
     query.setRenderer(request.getRenderer());
 
+    // If the request body exists, copy the requstInfoProperties from it.  This map should contain
+    // the _directives_ specified in the request.
+    RequestBody body = request.getBody();
+    if(body != null) {
+      query.setRequestInfoProps(body.getRequestInfoProperties());
+    }
+
     try {
       addFieldsToQuery(request, query);
     } catch (IllegalArgumentException e) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/main/java/org/apache/ambari/server/api/query/Query.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/query/Query.java b/ambari-server/src/main/java/org/apache/ambari/server/api/query/Query.java
index fff842a..698b055 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/query/Query.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/query/Query.java
@@ -29,6 +29,7 @@ import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.TemporalInfo;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 
+import java.util.Map;
 import java.util.Set;
 
 
@@ -115,4 +116,20 @@ public interface Query {
    * @param renderer  renderer for the query
    */
   public void setRenderer(Renderer renderer);
+
+  /**
+   * Set this Query's requestInfoProperties from the original request.  This will contain information
+   * such as directives.
+   *
+   * @param requestInfoProperties a map a request info properties
+   */
+  void setRequestInfoProps(Map<String, String> requestInfoProperties);
+
+  /**
+   * Get this Query's requestInfoProperties from the original request.  This will contain information
+   * such as directives.
+   *
+   * @return a map a request info properties
+   */
+  Map<String, String> getRequestInfoProps();
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/main/java/org/apache/ambari/server/api/query/QueryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/query/QueryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/query/QueryImpl.java
index 18fd94b..eb3bd76 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/query/QueryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/query/QueryImpl.java
@@ -94,6 +94,11 @@ public class QueryImpl implements Query, ResourceInstance {
   private final Map<Resource.Type, String> keyValueMap = new HashMap<Resource.Type, String>();
 
   /**
+   * Map of properties from the request.
+   */
+  private final Map<String, String> requestInfoProperties = new HashMap<String, String>();
+
+  /**
    * Set of query results.
    */
   Map<Resource, QueryResult> queryResults = new LinkedHashMap<Resource, QueryResult>();
@@ -249,6 +254,18 @@ public class QueryImpl implements Query, ResourceInstance {
     renderer.init(clusterController);
   }
 
+  @Override
+  public void setRequestInfoProps(Map<String, String> requestInfoProperties) {
+    if(requestInfoProperties != null) {
+      this.requestInfoProperties.putAll(requestInfoProperties);
+    }
+  }
+
+  @Override
+  public Map<String, String> getRequestInfoProps() {
+    return this.requestInfoProperties;
+  }
+
 
 // ----- ResourceInstance --------------------------------------------------
 
@@ -967,7 +984,8 @@ public class QueryImpl implements Query, ResourceInstance {
   }
 
   private Request createRequest() {
-    Map<String, String> requestInfoProperties = new HashMap<String, String>();
+    // Initiate this request's requestInfoProperties with the ones set from the original request
+    Map<String, String> requestInfoProperties = new HashMap<String, String>(this.requestInfoProperties);
 
     if (pageRequest != null) {
       requestInfoProperties.put(BaseRequest.PAGE_SIZE_PROPERTY_KEY,

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BaseResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BaseResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BaseResourceDefinition.java
index dcc5217..aaeed43 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BaseResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/BaseResourceDefinition.java
@@ -33,10 +33,12 @@ import org.apache.commons.codec.EncoderException;
 import org.apache.commons.codec.net.URLCodec;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -52,12 +54,12 @@ public abstract class BaseResourceDefinition implements ResourceDefinition {
   /**
    * The sub-resource type definitions.
    */
-  private final Set<SubResourceDefinition> subResourceDefinitions;
+  private final Set<SubResourceDefinition> subResourceDefinitions = new HashSet<SubResourceDefinition>();
 
   /**
-   * The set of create directives for the resource which can be modified by sub resources.
+   * A map of directives for the different request types, each entry is expected to be modifiable by sub resources.
    */
-  private final Collection<String> createDirectives = new HashSet<String>();
+  private final Map<DirectiveType, Collection<String>> directives = new HashMap<DirectiveType, Collection<String>>();
 
   /**
    * Constructor.
@@ -65,8 +67,7 @@ public abstract class BaseResourceDefinition implements ResourceDefinition {
    * @param resourceType resource type
    */
   public BaseResourceDefinition(Resource.Type resourceType) {
-    m_type = resourceType;
-    subResourceDefinitions = Collections.emptySet();
+    this(resourceType, null, null);
   }
 
   /**
@@ -76,31 +77,31 @@ public abstract class BaseResourceDefinition implements ResourceDefinition {
    * @param subTypes      the sub-resource types
    */
   public BaseResourceDefinition(Resource.Type resourceType, Resource.Type ... subTypes) {
-    m_type = resourceType;
-    subResourceDefinitions =  new HashSet<SubResourceDefinition>();
-
-    for (Resource.Type subType : subTypes) {
-      subResourceDefinitions.add(new SubResourceDefinition(subType));
-    }
+    this(resourceType, (subTypes == null) ? null : Arrays.asList(subTypes), null);
   }
 
   /**
    * Constructor.
    *
-   * @param resourceType      the resource type
-   * @param subTypes          the sub-resource types
-   * @param createDirectives  the set of create directives for the resource
+   * @param resourceType the resource type
+   * @param subTypes     the sub-resource types
+   * @param directives   a map of directives for request types for this resource
    */
   public BaseResourceDefinition(Resource.Type resourceType,
-                                Set<Resource.Type> subTypes,
-                                Collection<String> createDirectives) {
+                                Collection<Resource.Type> subTypes,
+                                Map<DirectiveType, ? extends Collection<String>> directives) {
     m_type = resourceType;
-    subResourceDefinitions =  new HashSet<SubResourceDefinition>();
 
-    for (Resource.Type subType : subTypes) {
-      subResourceDefinitions.add(new SubResourceDefinition(subType));
+    if (subTypes != null) {
+      for (Resource.Type subType : subTypes) {
+        subResourceDefinitions.add(new SubResourceDefinition(subType));
+      }
     }
-    this.createDirectives.addAll(createDirectives);
+
+    initializeDirectives(DirectiveType.READ, directives);
+    initializeDirectives(DirectiveType.CREATE, directives);
+    initializeDirectives(DirectiveType.UPDATE, directives);
+    initializeDirectives(DirectiveType.DELETE, directives);
   }
 
   @Override
@@ -141,19 +142,27 @@ public abstract class BaseResourceDefinition implements ResourceDefinition {
   }
 
   @Override
+  public Collection<String> getReadDirectives() {
+    // return a collection which can be modified by sub resources
+    return directives.get(DirectiveType.READ);
+  }
+
+  @Override
   public Collection<String> getCreateDirectives() {
     // return a collection which can be modified by sub resources
-    return createDirectives;
+    return directives.get(DirectiveType.CREATE);
   }
 
   @Override
   public Collection<String> getUpdateDirectives() {
-    return new HashSet<>();
+    // return a collection which can be modified by sub resources
+    return directives.get(DirectiveType.UPDATE);
   }
 
   @Override
   public Collection<String> getDeleteDirectives() {
-    return new HashSet<>();
+    // return a collection which can be modified by sub resources
+    return directives.get(DirectiveType.DELETE);
   }
 
   @Override
@@ -225,4 +234,27 @@ public abstract class BaseResourceDefinition implements ResourceDefinition {
       }
     }
   }
+
+  /**
+   * Initializes the specified collection of directives into a modifiable set of directives for the specified type of directives.
+   *
+   * @param type       a request type
+   * @param directives the map of directives from which to copy
+   */
+  private void initializeDirectives(DirectiveType type, Map<DirectiveType, ? extends Collection<String>> directives) {
+    HashSet<String> requestDirectives = new HashSet<String>();
+
+    if ((directives != null) && directives.get(type) != null) {
+      requestDirectives.addAll(directives.get(type));
+    }
+
+    this.directives.put(type, requestDirectives);
+  }
+
+  public enum DirectiveType {
+    CREATE,
+    READ,
+    UPDATE,
+    DELETE
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceDefinition.java
index 8df1a02..e437a03 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceDefinition.java
@@ -81,6 +81,15 @@ public interface ResourceDefinition {
   Renderer getRenderer(String name) throws IllegalArgumentException;
 
   /**
+   * Obtain the set of read directives for the resource.  A get directive is
+   * information that can be provided in the query string of a GET operation for
+   * the resource.  These directives are not predicates but are put into the
+   * map of request info properties used by the resource provider when getting
+   * the resource.
+   */
+  Collection<String> getReadDirectives();
+
+  /**
    * Obtain the set of create directives for the resource.  A create directive is
    * information that can be provided in the query string of a POST operation for
    * the resource.  These directives are not predicates but are put into the

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/main/java/org/apache/ambari/server/api/resources/SimpleResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/SimpleResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/SimpleResourceDefinition.java
index 394e295..68cbb54 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/SimpleResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/SimpleResourceDefinition.java
@@ -20,8 +20,9 @@ package org.apache.ambari.server.api.resources;
 
 import org.apache.ambari.server.controller.spi.Resource;
 
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Set;
+import java.util.Map;
 
 /**
  * Simple concrete resource definition.
@@ -43,35 +44,34 @@ public class SimpleResourceDefinition extends BaseResourceDefinition {
 
   /**
    * Constructor.
-   * @param resourceType  the resource type
-   * @param singularName  the resource singular name
-   * @param pluralName    the resource plural name
-   * @param subTypes      the sub-resource types
    *
+   * @param resourceType the resource type
+   * @param singularName the resource singular name
+   * @param pluralName   the resource plural name
+   * @param subTypes     the sub-resource types
+   * @see #SimpleResourceDefinition(Resource.Type, String, String, Collection, Map)
    */
   public SimpleResourceDefinition(Resource.Type resourceType, String singularName, String pluralName,
                                   Resource.Type... subTypes) {
-    super(resourceType, subTypes);
-
-    this.singularName = singularName;
-    this.pluralName   = pluralName;
+    this(resourceType, singularName, pluralName, (subTypes == null) ? null : Arrays.asList(subTypes), null);
   }
 
   /**
    * Constructor.
-   * @param resourceType      the resource type
-   * @param singularName      the resource singular name
-   * @param pluralName        the resource plural name
-   * @param subTypes          the sub-resource types
-   * @param createDirectives  the set of create directives for the resource
+   *
+   * @param resourceType the resource type
+   * @param singularName the resource singular name
+   * @param pluralName   the resource plural name
+   * @param subTypes     the sub-resource types
+   * @param directives   the a map of directives for the different request types
    */
   public SimpleResourceDefinition(Resource.Type resourceType, String singularName, String pluralName,
-                                  Set<Resource.Type> subTypes,
-                                  Collection<String> createDirectives) {
-    super(resourceType, subTypes, createDirectives);
+                                  Collection<Resource.Type> subTypes,
+                                  Map<DirectiveType, ? extends Collection<String>> directives) {
+    super(resourceType, subTypes, directives);
 
     this.singularName = singularName;
-    this.pluralName   = pluralName;
+    this.pluralName = pluralName;
   }
 
   // ----- ResourceDefinition ------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
index bf7860b..7018818 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
@@ -35,7 +35,10 @@ public class UpgradeResourceDefinition extends SimpleResourceDefinition {
    * Constructor.
    */
   public UpgradeResourceDefinition() {
-    super(Resource.Type.Upgrade, "upgrade", "upgrades", Collections.singleton(Resource.Type.UpgradeGroup),
-        Arrays.asList(DOWNGRADE_DIRECTIVE, SKIP_SERVICE_CHECKS_DIRECTIVE));
+    super(Resource.Type.Upgrade,
+        "upgrade",
+        "upgrades",
+        Collections.singleton(Resource.Type.UpgradeGroup),
+        Collections.singletonMap(DirectiveType.CREATE, Arrays.asList(DOWNGRADE_DIRECTIVE, SKIP_SERVICE_CHECKS_DIRECTIVE)));
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java
index 0ebeb19..9f7b949 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java
@@ -329,6 +329,9 @@ public abstract class BaseRequest implements Request {
           case POST:
             ignoredProperties = m_resource.getResourceDefinition().getCreateDirectives();
             break;
+          case GET:
+            ignoredProperties = m_resource.getResourceDefinition().getReadDirectives();
+            break;
           case DELETE:
             ignoredProperties = m_resource.getResourceDefinition().getDeleteDirectives();
             break;

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java
index 19fee8e..2f71776 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java
@@ -46,7 +46,7 @@ public class RequestFactory {
                                ResourceInstance resource) {
     switch (requestType) {
       case GET:
-        return new GetRequest(headers, body, uriInfo, resource);
+        return createGetRequest(headers, body, uriInfo, resource);
       case PUT:
         return createPutRequest(headers, body, uriInfo, resource);
       case DELETE:
@@ -59,6 +59,19 @@ public class RequestFactory {
   }
 
   /**
+   * Create a GET request.  This will apply any eligible directives supplied in the URI.
+   *
+   * @param headers  http headers
+   * @param uriInfo  uri information
+   * @param resource associated resource instance
+   * @return new post request
+   */
+  private Request createGetRequest(HttpHeaders headers, RequestBody body, UriInfo uriInfo, ResourceInstance resource) {
+    applyDirectives(Request.Type.GET, body, uriInfo, resource);
+    return new GetRequest(headers, body, uriInfo, resource);
+  }
+
+  /**
    * Create a POST request.  This will either be a standard post request or a query post request.
    * A query post request first applies a query to a collection resource and then creates
    * sub-resources to all matches of the predicate.
@@ -152,6 +165,9 @@ public class RequestFactory {
         case POST:
           directives = resourceDefinition.getCreateDirectives();
           break;
+        case GET:
+          directives = resourceDefinition.getReadDirectives();
+          break;
         case DELETE:
           directives = resourceDefinition.getDeleteDirectives();
           break;

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/ReadHandlerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/ReadHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/ReadHandlerTest.java
index 5cb601e..ee97de3 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/ReadHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/ReadHandlerTest.java
@@ -23,6 +23,7 @@ import org.apache.ambari.server.api.query.render.DefaultRenderer;
 import org.apache.ambari.server.api.query.render.Renderer;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 import org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.api.services.RequestBody;
 import org.apache.ambari.server.api.services.Result;
 import org.apache.ambari.server.api.services.ResultStatus;
 import org.apache.ambari.server.controller.spi.*;
@@ -83,9 +84,12 @@ public class ReadHandlerTest {
     Query query = createMock(Query.class);
     Predicate predicate = createMock(Predicate.class);
     Result result = createStrictMock(Result.class);
+    RequestBody body = createStrictMock(RequestBody.class);
     Renderer renderer = new DefaultRenderer();
     Capture<ResultStatus> resultStatusCapture = new Capture<ResultStatus>();
 
+    Map<String, String> requestInfoProperties = Collections.singletonMap("directive", "value");
+
     Map<String, TemporalInfo> mapPartialResponseFields = new HashMap<String, TemporalInfo>();
     mapPartialResponseFields.put("foo", null);
     mapPartialResponseFields.put("bar/c", null);
@@ -98,8 +102,12 @@ public class ReadHandlerTest {
     expect(request.getPageRequest()).andReturn(null);
     expect(request.getSortRequest()).andReturn(null);
     expect(request.getRenderer()).andReturn(renderer);
+    expect(request.getBody()).andReturn(body);
     expect(request.getFields()).andReturn(mapPartialResponseFields);
 
+    expect(body.getRequestInfoProperties()).andReturn(requestInfoProperties);
+
+    query.setRequestInfoProps(requestInfoProperties);
     query.addProperty("foo", null);
     query.addProperty("bar/c", null);
     query.addProperty("bar/d/e", null);
@@ -113,13 +121,13 @@ public class ReadHandlerTest {
     expect(query.execute()).andReturn(result);
     result.setResultStatus(capture(resultStatusCapture));
 
-    replay(request, resource, query, predicate, result);
+    replay(request, resource, body, query, predicate, result);
 
     //test
     ReadHandler handler = new ReadHandler();
     assertSame(result, handler.handleRequest(request));
     assertEquals(ResultStatus.STATUS.OK, resultStatusCapture.getValue().getStatus());
-    verify(request, resource, query, predicate, result);
+    verify(request, resource, body, query, predicate, result);
   }
 
   @Test
@@ -136,6 +144,7 @@ public class ReadHandlerTest {
     expect(request.getPageRequest()).andReturn(null);
     expect(request.getSortRequest()).andReturn(null);
     expect(request.getRenderer()).andReturn(renderer);
+    expect(request.getBody()).andReturn(null);
     expect(request.getFields()).andReturn(Collections.<String, TemporalInfo>emptyMap());
 
     expect(request.getQueryPredicate()).andReturn(predicate);
@@ -171,6 +180,7 @@ public class ReadHandlerTest {
     expect(request.getPageRequest()).andReturn(null);
     expect(request.getSortRequest()).andReturn(null);
     expect(request.getRenderer()).andReturn(renderer);
+    expect(request.getBody()).andReturn(null);
     expect(request.getFields()).andReturn(Collections.<String, TemporalInfo>emptyMap());
 
     expect(request.getQueryPredicate()).andReturn(predicate);
@@ -207,6 +217,7 @@ public class ReadHandlerTest {
     expect(request.getPageRequest()).andReturn(null);
     expect(request.getSortRequest()).andReturn(null);
     expect(request.getRenderer()).andReturn(renderer);
+    expect(request.getBody()).andReturn(null);
     expect(request.getFields()).andReturn(Collections.<String, TemporalInfo>emptyMap());
 
     expect(request.getQueryPredicate()).andReturn(predicate);
@@ -242,6 +253,7 @@ public class ReadHandlerTest {
     expect(request.getPageRequest()).andReturn(null);
     expect(request.getSortRequest()).andReturn(null);
     expect(request.getRenderer()).andReturn(renderer);
+    expect(request.getBody()).andReturn(null);
     expect(request.getFields()).andReturn(Collections.<String, TemporalInfo>emptyMap());
 
     expect(request.getQueryPredicate()).andReturn(predicate).anyTimes();
@@ -276,6 +288,7 @@ public class ReadHandlerTest {
     expect(request.getPageRequest()).andReturn(null);
     expect(request.getSortRequest()).andReturn(null);
     expect(request.getRenderer()).andReturn(renderer);
+    expect(request.getBody()).andReturn(null);
     expect(request.getFields()).andReturn(Collections.<String, TemporalInfo>emptyMap());
 
     expect(request.getQueryPredicate()).andReturn(null).anyTimes();
@@ -311,6 +324,7 @@ public class ReadHandlerTest {
     expect(request.getPageRequest()).andReturn(null);
     expect(request.getSortRequest()).andReturn(null);
     expect(request.getRenderer()).andReturn(renderer);
+    expect(request.getBody()).andReturn(null);
     expect(request.getFields()).andReturn(Collections.<String, TemporalInfo>emptyMap());
 
     expect(request.getQueryPredicate()).andReturn(predicate);

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
index f174cb6..46f3ef7 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
@@ -50,7 +50,9 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -143,14 +145,23 @@ public class BaseResourceDefinitionTest {
   }
 
   @Test
-  public void testGetCreateDirectives() {
+  public void testReadDirectives() {
     ResourceDefinition resource = getResourceDefinition();
 
-    assertEquals(Collections.EMPTY_SET, resource.getCreateDirectives());
+    assertEquals(Collections.EMPTY_SET, resource.getReadDirectives());
 
-    resource = getResourceDefinition("do_something", "do_something_else");
+    Map<BaseResourceDefinition.DirectiveType, List<String>> directives = new HashMap<BaseResourceDefinition.DirectiveType, List<String>>();
+    directives.put(BaseResourceDefinition.DirectiveType.DELETE, Arrays.asList("do_something_delete", "do_something_else_delete"));
+    directives.put(BaseResourceDefinition.DirectiveType.READ, Arrays.asList("do_something_get", "do_something_else_get"));
+    directives.put(BaseResourceDefinition.DirectiveType.CREATE, Arrays.asList("do_something_post", "do_something_else_post"));
+    directives.put(BaseResourceDefinition.DirectiveType.UPDATE, Arrays.asList("do_something_put", "do_something_else_put"));
 
-    assertEquals(new HashSet<String>() {{add("do_something"); add("do_something_else");}}, resource.getCreateDirectives());
+    resource = getResourceDefinition(directives);
+
+    assertEquals(new HashSet<String>() {{add("do_something_delete"); add("do_something_else_delete");}}, resource.getDeleteDirectives());
+    assertEquals(new HashSet<String>() {{add("do_something_get"); add("do_something_else_get");}}, resource.getReadDirectives());
+    assertEquals(new HashSet<String>() {{add("do_something_post"); add("do_something_else_post");}}, resource.getCreateDirectives());
+    assertEquals(new HashSet<String>() {{add("do_something_put"); add("do_something_else_put");}}, resource.getUpdateDirectives());
   }
 
   private BaseResourceDefinition getResourceDefinition() {
@@ -167,9 +178,9 @@ public class BaseResourceDefinitionTest {
     };
   }
 
-  private BaseResourceDefinition getResourceDefinition(String ... createDirectives) {
+  private BaseResourceDefinition getResourceDefinition(Map<BaseResourceDefinition.DirectiveType, ? extends Collection<String>> directives) {
     return new BaseResourceDefinition(Resource.Type.Service,
-        Collections.<Resource.Type>emptySet(), new HashSet<String>(Arrays.asList(createDirectives))) {
+        Collections.<Resource.Type>emptySet(), directives) {
       @Override
       public String getPluralName() {
         return "pluralName";

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/test/java/org/apache/ambari/server/api/resources/SimpleResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/SimpleResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/SimpleResourceDefinitionTest.java
index 6169ee7..b0ad932 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/SimpleResourceDefinitionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/SimpleResourceDefinitionTest.java
@@ -21,10 +21,12 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.junit.Test;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
+import java.util.HashMap;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * SimpleResourceDefinition tests.
@@ -48,16 +50,43 @@ public class SimpleResourceDefinitionTest {
   }
 
   @Test
-  public void testGetCreateDirectives() {
-    ResourceDefinition resourceDefinition =
-        new SimpleResourceDefinition(Resource.Type.Stage, "stage", "stages", Resource.Type.Task);
+  public void testDirectives() {
+    ResourceDefinition resourceDefinition;
+
+    resourceDefinition = new SimpleResourceDefinition(Resource.Type.Stage, "stage", "stages",
+        Resource.Type.Task);
+
+    validateDirectives(Collections.<String>emptySet(), resourceDefinition.getCreateDirectives());
+    validateDirectives(Collections.<String>emptySet(), resourceDefinition.getReadDirectives());
+    validateDirectives(Collections.<String>emptySet(), resourceDefinition.getUpdateDirectives());
+    validateDirectives(Collections.<String>emptySet(), resourceDefinition.getDeleteDirectives());
 
-    assertEquals(Collections.EMPTY_SET, resourceDefinition.getCreateDirectives());
+    HashMap<BaseResourceDefinition.DirectiveType, Collection<String>> directives = new HashMap<BaseResourceDefinition.DirectiveType, Collection<String>>();
+    directives.put(BaseResourceDefinition.DirectiveType.CREATE, Arrays.asList("POST1", "POST2"));
+    directives.put(BaseResourceDefinition.DirectiveType.READ, Arrays.asList("GET1", "GET2"));
+    directives.put(BaseResourceDefinition.DirectiveType.UPDATE, Arrays.asList("PUT1", "PUT2"));
+    directives.put(BaseResourceDefinition.DirectiveType.DELETE, Arrays.asList("DEL1", "DEL2"));
 
     resourceDefinition = new SimpleResourceDefinition(Resource.Type.Stage, "stage", "stages",
-            Collections.singleton(Resource.Type.Task), Arrays.asList("do_something", "do_something_else"));
+        Collections.singleton(Resource.Type.Task), directives);
+
+    validateDirectives(directives.get(BaseResourceDefinition.DirectiveType.CREATE), resourceDefinition.getCreateDirectives());
+    validateDirectives(directives.get(BaseResourceDefinition.DirectiveType.READ), resourceDefinition.getReadDirectives());
+    validateDirectives(directives.get(BaseResourceDefinition.DirectiveType.UPDATE), resourceDefinition.getUpdateDirectives());
+    validateDirectives(directives.get(BaseResourceDefinition.DirectiveType.DELETE), resourceDefinition.getDeleteDirectives());
+  }
+
+  private void validateDirectives(Collection<String> expected, Collection<String> actual) {
+    int actualSize = actual.size();
+
+    // Ensure the collection is empty...
+    assertEquals(expected.size(), actual.size());
+    for (String actualItem : actual) {
+      assertTrue(expected.contains(actualItem));
+    }
 
-    assertEquals(new HashSet<String>() {{add("do_something"); add("do_something_else");}},
-        resourceDefinition.getCreateDirectives());
+    // Ensure the collection is modifiable...
+    assertTrue(actual.add("DIRECTIVE"));
+    assertEquals(actualSize + 1, actual.size());
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/test/java/org/apache/ambari/server/api/services/RequestFactoryTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/RequestFactoryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/RequestFactoryTest.java
index 11568c9..ee37a49 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/RequestFactoryTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/RequestFactoryTest.java
@@ -325,4 +325,42 @@ public class RequestFactoryTest {
 
     verify(headers, uriInfo, body, resource, mapQueryParams, resourceDefinition);
   }
+
+  @Test
+  // get with create directive in URI
+  public void testCreate_Get__WithUriDirective() {
+    HttpHeaders headers = createMock(HttpHeaders.class);
+    UriInfo uriInfo = createMock(UriInfo.class);
+    RequestBody body = createMock(RequestBody.class);
+    ResourceInstance resource = createMock(ResourceInstance.class);
+    ResourceDefinition resourceDefinition = createMock(ResourceDefinition.class);
+
+    @SuppressWarnings("unchecked")
+    MultivaluedMap<String, String> mapQueryParams = createMock(MultivaluedMap.class);
+    Map<String, List<String>> mapProps = new HashMap<String, List<String>>();
+    mapProps.put("foo", Collections.singletonList("bar"));
+
+    Map<String, String> requestInfoMap = new HashMap<String, String>();
+
+    //expectations
+    expect(uriInfo.getQueryParameters()).andReturn(mapQueryParams).anyTimes();
+    expect(mapQueryParams.entrySet()).andReturn(mapProps.entrySet()).anyTimes();
+    expect(resource.getResourceDefinition()).andReturn(resourceDefinition).anyTimes();
+    expect(resourceDefinition.getReadDirectives()).andReturn(Collections.singleton("foo"));
+    expect(body.getQueryString()).andReturn(null);
+    expect(body.getRequestInfoProperties()).andReturn(requestInfoMap).anyTimes();
+
+    replay(headers, uriInfo, body, resource, mapQueryParams, resourceDefinition);
+
+    //test
+    RequestFactory factory = new RequestFactory();
+    Request request = factory.createRequest(headers, body, uriInfo, Request.Type.GET, resource);
+
+    assertEquals(resource, request.getResource());
+    assertEquals(body, request.getBody());
+    assertEquals(Request.Type.GET, request.getRequestType());
+    assertEquals("bar", requestInfoMap.get("foo"));
+
+    verify(headers, uriInfo, body, resource, mapQueryParams, resourceDefinition);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/91be5886/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/AuditEventCreatorTestHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/AuditEventCreatorTestHelper.java b/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/AuditEventCreatorTestHelper.java
index 2642418..f1a0ad0 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/AuditEventCreatorTestHelper.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/AuditEventCreatorTestHelper.java
@@ -140,6 +140,11 @@ public class AuditEventCreatorTestHelper {
               }
 
               @Override
+              public Collection<String> getReadDirectives() {
+                return null;
+              }
+
+              @Override
               public boolean isCreatable() {
                 return false;
               }