Bläddra i källkod

AMBARI-4981 - Cannot stop selected services via API

tbeerbower 11 år sedan
förälder
incheckning
5c95b13c98

+ 36 - 18
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java

@@ -52,16 +52,17 @@ public abstract class AbstractResourceProvider extends BaseProvider implements R
    */
   private final Set<ResourceProviderObserver> observers = new HashSet<ResourceProviderObserver>();
 
-
   protected final static Logger LOG =
       LoggerFactory.getLogger(AbstractResourceProvider.class);
 
-    // ----- Constructors ------------------------------------------------------
+
+  // ----- Constructors ------------------------------------------------------
+
   /**
-   * Create a  new resource provider for the given management controller.
+   * Create a  new resource provider.
    *
-   * @param propertyIds           the property ids
-   * @param keyPropertyIds        the key property ids
+   * @param propertyIds     the property ids
+   * @param keyPropertyIds  the key property ids
    */
   protected AbstractResourceProvider(Set<String> propertyIds,
                                      Map<Resource.Type, String> keyPropertyIds) {
@@ -161,11 +162,11 @@ public abstract class AbstractResourceProvider extends BaseProvider implements R
 
   /**
    * Get a set of properties from the given property map and predicate.  The
-   * returned set of property/value mappings is required to generate update or create
-   * requests to the back end which does not deal with predicates.  Note that
+   * returned set of property/value mappings is required to generate update
+   * requests to the back end which does not deal with Predicates.  Note that
    * the single property map & predicate can result in multiple backend requests.
    *
-   * @param requestPropertyMap  the request properties (for update)
+   * @param requestPropertyMap  the request update properties; may not be null
    * @param givenPredicate      the predicate
    *
    * @return the set of properties used to build request objects
@@ -175,21 +176,20 @@ public abstract class AbstractResourceProvider extends BaseProvider implements R
 
     Set<Map<String, Object>> propertyMaps = new HashSet<Map<String, Object>>();
 
-    Set<String> pkPropertyIds = getPKPropertyIds();
-    if (requestPropertyMap != null && !pkPropertyIds.equals(PredicateHelper.getPropertyIds(givenPredicate))) {
-
-      for (Resource resource : getResources(PropertyHelper.getReadRequest(pkPropertyIds), givenPredicate)) {
+    // If the predicate specifies a unique resource then we can simply return a single
+    // property map for the update.  Otherwise we need to do a get with the given predicate
+    // to get the set of property maps for the resources that need to be updated.
+    if (specifiesUniqueResource(givenPredicate)) {
+      Map<String, Object> propertyMap = new HashMap<String, Object>(PredicateHelper.getProperties(givenPredicate));
+      propertyMap.putAll(requestPropertyMap);
+      propertyMaps.add(propertyMap);
+    } else {
+      for (Resource resource : getResources(givenPredicate)) {
         Map<String, Object> propertyMap = new HashMap<String, Object>(PropertyHelper.getProperties(resource));
         propertyMap.putAll(requestPropertyMap);
         propertyMaps.add(propertyMap);
       }
     }
-    else {
-      Map<String, Object> propertyMap = new HashMap<String, Object>(PredicateHelper.getProperties(givenPredicate));
-      propertyMap.putAll(requestPropertyMap);
-      propertyMaps.add(propertyMap);
-    }
-
     return propertyMaps;
   }
 
@@ -340,6 +340,24 @@ public abstract class AbstractResourceProvider extends BaseProvider implements R
     return config;
   }
 
+  // get the resources (id fields only) for the given predicate.
+  private Set<Resource> getResources(Predicate givenPredicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+    // TODO : Check for case where we should pass the request out to the cluster controller.
+    return getResources(PropertyHelper.getReadRequest(getPKPropertyIds()), givenPredicate);
+  }
+
+  // determine whether or not the given predicate specifies a unique resource for this provider.
+  private boolean specifiesUniqueResource(Predicate predicate) {
+    SimplifyingPredicateVisitor visitor = new SimplifyingPredicateVisitor(this);
+    PredicateHelper.visit(predicate, visitor);
+    List<Predicate> predicates = visitor.getSimplifiedPredicates();
+
+    return predicates.size() == 1 && PredicateHelper.getPropertyIds(predicate).containsAll(getPKPropertyIds());
+  }
+
+
   // ----- Inner interface ---------------------------------------------------
 
   /**

+ 176 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java

@@ -20,6 +20,7 @@ package org.apache.ambari.server.controller.internal;
 
 import static org.easymock.EasyMock.createMock;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -35,8 +36,17 @@ import org.apache.ambari.server.controller.ServiceComponentHostRequest;
 import org.apache.ambari.server.controller.StackConfigurationRequest;
 import org.apache.ambari.server.controller.TaskStatusRequest;
 import org.apache.ambari.server.controller.UserRequest;
+import org.apache.ambari.server.controller.predicate.AlwaysPredicate;
+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.PredicateBuilder;
 import org.easymock.EasyMock;
 import org.easymock.IArgumentMatcher;
 import org.junit.Assert;
@@ -151,6 +161,70 @@ public class AbstractResourceProviderTest {
     Assert.assertEquals(associatedResources, status.getAssociatedResources());
   }
 
+  @Test
+  public void testGetPropertyMaps() throws Exception {
+    AbstractResourceProvider provider = new TestResourceProvider();
+
+    Map<String, Object> updatePropertyMap = new HashMap<String, Object>();
+    updatePropertyMap.put("SomeProperty", "SomeUpdateValue");
+    updatePropertyMap.put("SomeOtherProperty", 99);
+
+    // get the property map to update resource
+    // where ClusterName=c1 and ResourceName=r1
+    PredicateBuilder pb = new PredicateBuilder();
+    Predicate predicate = pb.property("ClusterName").equals("c1").and().property("ResourceName").equals("r1").toPredicate();
+
+    Set<Map<String, Object>> propertyMaps = provider.getPropertyMaps(updatePropertyMap, predicate);
+
+    Assert.assertEquals(1, propertyMaps.size());
+
+    Map<String, Object> map = propertyMaps.iterator().next();
+
+    Assert.assertEquals(4, map.size());
+    Assert.assertEquals("c1", map.get("ClusterName"));
+    Assert.assertEquals("r1", map.get("ResourceName"));
+    Assert.assertEquals("SomeUpdateValue", map.get("SomeProperty"));
+    Assert.assertEquals(99, map.get("SomeOtherProperty"));
+
+    // get the property maps to update resources
+    // where ClusterName=c1 and (ResourceName=r1 or ResourceName=r2)
+    pb = new PredicateBuilder();
+    predicate = pb.property("ClusterName").equals("c1").and().
+        begin().
+          property("ResourceName").equals("r1").or().property("ResourceName").equals("r2").
+        end().toPredicate();
+
+    propertyMaps = provider.getPropertyMaps(updatePropertyMap, predicate);
+
+    Assert.assertEquals(2, propertyMaps.size());
+
+    for (Map<String, Object> map2 : propertyMaps) {
+      Assert.assertEquals(4, map2.size());
+      Assert.assertEquals("c1", map2.get("ClusterName"));
+      Object resourceName = map2.get("ResourceName");
+      Assert.assertTrue(resourceName.equals("r1") || resourceName.equals("r2"));
+      Assert.assertEquals("SomeUpdateValue", map2.get("SomeProperty"));
+      Assert.assertEquals(99, map2.get("SomeOtherProperty"));
+    }
+
+    // get the property maps to update all resources
+    predicate = new AlwaysPredicate();
+
+    propertyMaps = provider.getPropertyMaps(updatePropertyMap, predicate);
+
+    Assert.assertEquals(4, propertyMaps.size());
+
+    for (Map<String, Object> map2 : propertyMaps) {
+      Assert.assertEquals(4, map2.size());
+      Assert.assertEquals("c1", map2.get("ClusterName"));
+      Object resourceName = map2.get("ResourceName");
+      Assert.assertTrue(resourceName.equals("r1") || resourceName.equals("r2")||
+          resourceName.equals("r3") || resourceName.equals("r4"));
+      Assert.assertEquals("SomeUpdateValue", map2.get("SomeProperty"));
+      Assert.assertEquals(99, map2.get("SomeOtherProperty"));
+    }
+  }
+
 
   // ----- helper methods ----------------------------------------------------
 
@@ -531,4 +605,106 @@ public class AbstractResourceProviderTest {
       return lastEvent;
     }
   }
+
+
+  // ----- Test resource adapter ---------------------------------------------
+
+  private static Resource.Type testResourceType = new Resource.Type("testResource");
+
+  private static Set<String> pkPropertyIds =
+      new HashSet<String>(Arrays.asList(new String[]{
+          "ClusterName",
+          "ResourceName"}));
+
+  private static Set<String> propertyIds =
+      new HashSet<String>(Arrays.asList(new String[]{
+          "ClusterName",
+          "ResourceName",
+          "SomeProperty",
+          "SomeOtherProperty"}));
+
+  private static Map<Resource.Type, String> keyPropertyIds =
+      new HashMap<Resource.Type, String>();
+
+  static {
+    keyPropertyIds.put(Resource.Type.Cluster, "ClusterName");
+    keyPropertyIds.put(testResourceType, "ResourceName" );
+  }
+
+  private static Set<Resource> allResources = new HashSet<Resource>();
+
+  static {
+    Resource resource = new ResourceImpl(testResourceType);
+    resource.setProperty("ClusterName", "c1");
+    resource.setProperty("ResourceName", "r1");
+    resource.setProperty("SomeProperty", "SomeValue1");
+    resource.setProperty("SomeOtherProperty", 10);
+    allResources.add(resource);
+
+    resource = new ResourceImpl(testResourceType);
+    resource.setProperty("ClusterName", "c1");
+    resource.setProperty("ResourceName", "r2");
+    resource.setProperty("SomeProperty", "SomeValue2");
+    resource.setProperty("SomeOtherProperty", 100);
+    allResources.add(resource);
+
+    resource = new ResourceImpl(testResourceType);
+    resource.setProperty("ClusterName", "c1");
+    resource.setProperty("ResourceName", "r3");
+    resource.setProperty("SomeProperty", "SomeValue3");
+    resource.setProperty("SomeOtherProperty", 1000);
+    allResources.add(resource);
+
+    resource = new ResourceImpl(testResourceType);
+    resource.setProperty("ClusterName", "c1");
+    resource.setProperty("ResourceName", "r4");
+    resource.setProperty("SomeProperty", "SomeValue4");
+    resource.setProperty("SomeOtherProperty", 9999);
+    allResources.add(resource);
+  }
+
+  public static class TestResourceProvider extends AbstractResourceProvider {
+
+    protected TestResourceProvider() {
+      super(propertyIds, keyPropertyIds);
+    }
+
+    @Override
+    protected Set<String> getPKPropertyIds() {
+      return pkPropertyIds;
+
+    }
+
+    @Override
+    public RequestStatus createResources(Request request)
+        throws SystemException, UnsupportedPropertyException, ResourceAlreadyExistsException, NoSuchParentResourceException {
+      return new RequestStatusImpl(null);
+    }
+
+    @Override
+    public Set<Resource> getResources(Request request, Predicate predicate)
+        throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+      Set<Resource> resources = new HashSet<Resource>();
+
+      for(Resource resource : allResources) {
+        if (predicate.evaluate(resource)) {
+          resources.add(new ResourceImpl(resource, request.getPropertyIds()));
+        }
+      }
+      return resources;
+    }
+
+    @Override
+    public RequestStatus updateResources(Request request, Predicate predicate)
+        throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+      return new RequestStatusImpl(null);
+    }
+
+    @Override
+    public RequestStatus deleteResources(Predicate predicate)
+        throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+      return new RequestStatusImpl(null);
+    }
+  }
 }