AMBARI-21832. Reject PATCH VDFs with Services that are not Included in the 
Cluster (dlysnichenko)


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

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: c091ebe8afa1d83384d5607fb4ee52eb018772b0
Parents: c51540d
Author: Lisnichenko Dmitro <dlysniche...@hortonworks.com>
Authored: Mon Sep 4 19:33:11 2017 +0300
Committer: Lisnichenko Dmitro <dlysniche...@hortonworks.com>
Committed: Mon Sep 4 19:33:11 2017 +0300

----------------------------------------------------------------------
 .../ClusterStackVersionResourceProvider.java    | 45 +++++++++-
 ...ClusterStackVersionResourceProviderTest.java | 94 +++++++++++++++++++-
 2 files changed, 136 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c091ebe8/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
index 19f5895..3e4d4fd 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
@@ -20,6 +20,7 @@ package org.apache.ambari.server.controller.internal;
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.EnumSet;
@@ -77,6 +78,8 @@ import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.ServiceOsSpecific;
 import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.StackInfo;
+import org.apache.ambari.server.state.repository.AvailableService;
 import org.apache.ambari.server.state.repository.ClusterVersionSummary;
 import org.apache.ambari.server.state.repository.VersionDefinitionXml;
 import org.apache.ambari.server.state.stack.upgrade.RepositoryVersionHelper;
@@ -184,6 +187,9 @@ public class ClusterStackVersionResourceProvider extends 
AbstractControllerResou
   private static Gson gson;
 
   @Inject
+  private static Provider<AmbariMetaInfo> metaInfo;
+
+  @Inject
   private static Provider<Clusters> clusters;
 
   /**
@@ -558,6 +564,9 @@ public class ClusterStackVersionResourceProvider extends 
AbstractControllerResou
       // determine services for the repo
       Set<String> serviceNames = new HashSet<>();
 
+
+      checkPatchVDFAvailableServices(cluster, repoVersionEnt, 
desiredVersionDefinition);
+
       // !!! limit the serviceNames to those that are detailed for the 
repository.
       // TODO packages don't have component granularity
       if (RepositoryType.STANDARD != repoVersionEnt.getType()) {
@@ -596,6 +605,38 @@ public class ClusterStackVersionResourceProvider extends 
AbstractControllerResou
     return req;
   }
 
+  /**
+   * Reject PATCH VDFs with Services that are not included in the Cluster
+   * @param cluster cluster instance
+   * @param repoVersionEnt repo version entity
+   * @param desiredVersionDefinition VDF
+   * @throws IllegalArgumentException thrown if VDF includes services that are 
not installed
+   * @throws AmbariException thrown if could not load stack for repo 
repoVersionEnt
+   */
+  protected void checkPatchVDFAvailableServices(Cluster cluster, 
RepositoryVersionEntity repoVersionEnt,
+                                              VersionDefinitionXml 
desiredVersionDefinition) throws SystemException, AmbariException {
+    if (repoVersionEnt.getType() == RepositoryType.PATCH) {
+
+      Collection<String> notPresentServices = new ArrayList<>();
+      Collection<String> presentServices = new ArrayList<>();
+
+      presentServices.addAll(cluster.getServices().keySet());
+      final StackInfo stack;
+      stack = metaInfo.get().getStack(repoVersionEnt.getStackName(), 
repoVersionEnt.getStackVersion());
+
+      for (AvailableService availableService : 
desiredVersionDefinition.getAvailableServices(stack)) {
+        String name = availableService.getName();
+        if (!presentServices.contains(name)) {
+          notPresentServices.add(name);
+        }
+      }
+      if (!notPresentServices.isEmpty()) {
+        throw new IllegalArgumentException(String.format("%s VDF includes 
services that are not installed: %s",
+            RepositoryType.PATCH, StringUtils.join(notPresentServices, ",")));
+      }
+    }
+  }
+
   private ActionExecutionContext 
getHostVersionInstallCommand(RepositoryVersionEntity repoVersion,
       Cluster cluster, AmbariManagementController managementController, 
AmbariMetaInfo ami,
       final StackId stackId, Set<String> repoServices, Map<String, 
List<RepositoryEntity>> perOsRepos, Stage stage1, Host host)
@@ -685,7 +726,7 @@ public class ClusterStackVersionResourceProvider extends 
AbstractControllerResou
 
     RequestStageContainer requestStages = new RequestStageContainer(
             actionManager.getNextRequestId(), null, requestFactory, 
actionManager);
-    requestStages.setRequestContext(String.format(INSTALL_PACKAGES_FULL_NAME));
+    requestStages.setRequestContext(INSTALL_PACKAGES_FULL_NAME);
 
     return requestStages;
   }
@@ -729,7 +770,7 @@ public class ClusterStackVersionResourceProvider extends 
AbstractControllerResou
 
     compare = v2 - v1;
 
-    return (compare == 0) ? 0 : (compare < 0) ? -1 : 1;
+    return Integer.compare(compare, 0);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/c091ebe8/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
index f729de1..0e0e1c6 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
@@ -35,6 +35,7 @@ import java.lang.reflect.Field;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -89,11 +90,14 @@ import org.apache.ambari.server.state.MaintenanceState;
 import org.apache.ambari.server.state.RepositoryType;
 import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.ServiceOsSpecific;
 import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.StackInfo;
 import org.apache.ambari.server.state.cluster.ClusterImpl;
+import org.apache.ambari.server.state.repository.AvailableService;
 import org.apache.ambari.server.state.repository.VersionDefinitionXml;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.RepositoryVersionHelper;
@@ -1522,7 +1526,7 @@ public class ClusterStackVersionResourceProviderTest {
         "   }\n" +
         "]";
     
expect(repoVersion.getOperatingSystems()).andReturn(rvh.parseOperatingSystems(os_json)).anyTimes();
-    expect(repoVersion.getType()).andReturn(RepositoryType.STANDARD);
+    
expect(repoVersion.getType()).andReturn(RepositoryType.STANDARD).anyTimes();
 
     Map<String, Host> hostsForCluster = new HashMap<>();
     int hostCount = 2;
@@ -1806,6 +1810,94 @@ public class ClusterStackVersionResourceProviderTest {
 
   }
 
+  @Test
+  public void testCheckPatchVDFAvailableServices() throws Exception {
+    Cluster cluster = createNiceMock(Cluster.class);
+    RepositoryVersionEntity repoVersionEnt = 
createNiceMock(RepositoryVersionEntity.class);
+    VersionDefinitionXml desiredVersionDefinition = 
createNiceMock(VersionDefinitionXml.class);
+
+    expect(repoVersionEnt.getType()).andReturn(RepositoryType.PATCH).once();
+
+    Service service1 = createNiceMock(Service.class);
+    expect(service1.getName()).andReturn("SERVICE1").anyTimes();
+    expect(service1.getServiceComponents()).andReturn(new HashMap<String, 
ServiceComponent>());
+
+    Service service2 = createNiceMock(Service.class);
+    expect(service2.getName()).andReturn("SERVICE2").anyTimes();
+    expect(service2.getServiceComponents()).andReturn(new HashMap<String, 
ServiceComponent>());
+
+    Map<String, Service> clusterServices = new HashMap<>();
+    clusterServices.put("SERVICE1",service1);
+    clusterServices.put("SERVICE2",service2);
+
+    expect(cluster.getServices()).andReturn(clusterServices).once();
+    expect(repoVersionEnt.getStackName()).andReturn("HDP").once();
+    expect(repoVersionEnt.getStackVersion()).andReturn("2.5.0").once();
+
+    AvailableService availableService1 = 
createNiceMock(AvailableService.class);
+    expect(availableService1.getName()).andReturn("SERVICE1").anyTimes();
+
+    AvailableService availableService2 = 
createNiceMock(AvailableService.class);
+    expect(availableService2.getName()).andReturn("SERVICE2").anyTimes();
+
+    Collection<AvailableService> availableServices = new ArrayList<>();
+    availableServices.add(availableService1);
+    availableServices.add(availableService2);
+
+    
expect(desiredVersionDefinition.getAvailableServices((StackInfo)EasyMock.anyObject())).andReturn(availableServices).once();
+
+
+    replay(cluster, repoVersionEnt, desiredVersionDefinition, service1, 
service2, availableService1, availableService2);
+
+    ClusterStackVersionResourceProvider provider = new 
ClusterStackVersionResourceProvider(null);
+    injector.injectMembers(provider);
+    provider.checkPatchVDFAvailableServices(cluster, repoVersionEnt, 
desiredVersionDefinition);
+  }
+
+   @Test
+   public void testCheckPatchVDFAvailableServicesFail() throws Exception {
+     Cluster cluster = createNiceMock(Cluster.class);
+     RepositoryVersionEntity repoVersionEnt = 
createNiceMock(RepositoryVersionEntity.class);
+     VersionDefinitionXml desiredVersionDefinition = 
createNiceMock(VersionDefinitionXml.class);
+
+     expect(repoVersionEnt.getType()).andReturn(RepositoryType.PATCH).once();
+
+     Service service1 = createNiceMock(Service.class);
+     expect(service1.getName()).andReturn("SERVICE1").anyTimes();
+     expect(service1.getServiceComponents()).andReturn(new HashMap<String, 
ServiceComponent>());
+
+     Map<String, Service> clusterServices = new HashMap<>();
+     clusterServices.put("SERVICE1",service1);
+
+     expect(cluster.getServices()).andReturn(clusterServices).once();
+     expect(repoVersionEnt.getStackName()).andReturn("HDP").once();
+     expect(repoVersionEnt.getStackVersion()).andReturn("2.5.0").once();
+
+     AvailableService availableService1 = 
createNiceMock(AvailableService.class);
+     expect(availableService1.getName()).andReturn("SERVICE1").anyTimes();
+
+     AvailableService availableService2 = 
createNiceMock(AvailableService.class);
+     expect(availableService2.getName()).andReturn("SERVICE2").anyTimes();
+
+     Collection<AvailableService> availableServices = new ArrayList<>();
+     availableServices.add(availableService1);
+     availableServices.add(availableService2);
+
+     
expect(desiredVersionDefinition.getAvailableServices((StackInfo)EasyMock.anyObject())).andReturn(availableServices).once();
+
+
+     replay(cluster, repoVersionEnt, desiredVersionDefinition, service1, 
availableService1, availableService2);
+
+     ClusterStackVersionResourceProvider provider = new 
ClusterStackVersionResourceProvider(null);
+     injector.injectMembers(provider);
+     try {
+       provider.checkPatchVDFAvailableServices(cluster, repoVersionEnt, 
desiredVersionDefinition);
+       Assert.fail("Expected an exception when PATCH VDF includes services 
that are not installed");
+     } catch (IllegalArgumentException expected) {
+       // !!! expected
+       Assert.assertEquals(expected.getMessage(),"PATCH VDF includes services 
that are not installed: SERVICE2");
+     }
+   }
 
    private void testCreateResourcesExistingUpgrade(Authentication 
authentication) throws Exception {
     Resource.Type type = Resource.Type.ClusterStackVersion;

Reply via email to