AMBARI-21639. When Adding a New Service the Repository ID is Required (ncole)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/902ffc3d Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/902ffc3d Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/902ffc3d Branch: refs/heads/branch-2.6 Commit: 902ffc3d9c99de528a4c4efce3c63c1f9617fb6d Parents: 32216f7 Author: Nate Cole <nc...@hortonworks.com> Authored: Wed Aug 2 13:55:33 2017 -0400 Committer: Nate Cole <nc...@hortonworks.com> Committed: Wed Aug 2 14:24:50 2017 -0400 ---------------------------------------------------------------------- .../internal/ServiceResourceProvider.java | 27 +++ .../internal/ServiceResourceProviderTest.java | 232 ++++++++++++++++++- 2 files changed, 255 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/902ffc3d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java index b1f00e6..2b4bf3b 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java @@ -74,6 +74,7 @@ import org.apache.ambari.server.state.ServiceComponentHost; import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.state.State; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; @@ -1071,6 +1072,32 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider } Long desiredRepositoryVersion = request.getDesiredRepositoryVersionId(); + + if (null == desiredRepositoryVersion) { + Set<Long> repoIds = new HashSet<>(); + + for (Service service : cluster.getServices().values()) { + RepositoryVersionEntity serviceRepo = service.getDesiredRepositoryVersion(); + if (null != serviceRepo.getParentId()) { + repoIds.add(serviceRepo.getParentId()); + } else { + repoIds.add(serviceRepo.getId()); + } + } + + LOG.info("{} was not specified; the following repository ids were found: {}", + SERVICE_DESIRED_REPO_VERSION_ID_PROPERTY_ID, StringUtils.join(repoIds, ',')); + + if (CollectionUtils.isEmpty(repoIds)) { + throw new IllegalArgumentException("No repositories were found for service installation"); + } else if (repoIds.size() > 1) { + throw new IllegalArgumentException(String.format("%s was not specified, and the cluster " + + "contains more than one standard-type repository", SERVICE_DESIRED_REPO_VERSION_ID_PROPERTY_ID)); + } else { + desiredRepositoryVersion = repoIds.iterator().next(); + } + } + if (null == desiredRepositoryVersion) { throw new IllegalArgumentException(String.format("%s is required when adding a service.", SERVICE_DESIRED_REPO_VERSION_ID_PROPERTY_ID)); http://git-wip-us.apache.org/repos/asf/ambari/blob/902ffc3d/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java index a0c58ea..2bb7b7a 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java @@ -70,6 +70,7 @@ import org.apache.ambari.server.serveraction.kerberos.KerberosAdminAuthenticatio import org.apache.ambari.server.serveraction.kerberos.KerberosMissingAdminCredentialsException; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; +import org.apache.ambari.server.state.RepositoryType; import org.apache.ambari.server.state.Service; import org.apache.ambari.server.state.ServiceComponent; import org.apache.ambari.server.state.ServiceComponentHost; @@ -85,6 +86,8 @@ import org.junit.Test; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import com.google.common.collect.ImmutableMap; + /** * ServiceResourceProvider tests. */ @@ -140,7 +143,7 @@ public class ServiceResourceProviderTest { SecurityContextHolder.getContext().setAuthentication(authentication); - ResourceProvider provider = getServiceProvider(managementController, true); + ResourceProvider provider = getServiceProvider(managementController, true, null); // add the property map to a set for the request. add more maps for multiple creates Set<Map<String, Object>> propertySet = new LinkedHashSet<>(); @@ -1149,7 +1152,224 @@ public class ServiceResourceProviderTest { } } - private static ServiceResourceProvider getServiceProvider(AmbariManagementController managementController, boolean mockFindByStack) throws AmbariException { + @Test + public void testCreateWithNoRepositoryId() throws Exception { + AmbariManagementController managementController = createNiceMock(AmbariManagementController.class); + Clusters clusters = createNiceMock(Clusters.class); + Cluster cluster = createNiceMock(Cluster.class); + Service service1 = createNiceMock(Service.class); + Service service2 = createNiceMock(Service.class); + + RepositoryVersionEntity repoVersion = createNiceMock(RepositoryVersionEntity.class); + expect(repoVersion.getId()).andReturn(500L).anyTimes(); + expect(service1.getDesiredRepositoryVersion()).andReturn(repoVersion).atLeastOnce(); + + StackId stackId = new StackId("HDP-2.5"); + ServiceFactory serviceFactory = createNiceMock(ServiceFactory.class); + AmbariMetaInfo ambariMetaInfo = createNiceMock(AmbariMetaInfo.class); + ServiceInfo serviceInfo = createNiceMock(ServiceInfo.class); + + expect(managementController.getClusters()).andReturn(clusters).anyTimes(); + expect(managementController.getAmbariMetaInfo()).andReturn(ambariMetaInfo).anyTimes(); + + expect(cluster.addService(eq("Service200"), EasyMock.anyObject(RepositoryVersionEntity.class))).andReturn(service2); + + expect(clusters.getCluster("Cluster100")).andReturn(cluster).anyTimes(); + + expect(cluster.getServices()).andReturn( + ImmutableMap.<String, Service>builder() + .put("Service100", service1).build()).atLeastOnce(); + + expect(cluster.getDesiredStackVersion()).andReturn(stackId).anyTimes(); + expect(cluster.getClusterId()).andReturn(2L).anyTimes(); + + expect(ambariMetaInfo.isValidService( (String) anyObject(), (String) anyObject(), (String) anyObject())).andReturn(true); + expect(ambariMetaInfo.getService((String)anyObject(), (String)anyObject(), (String)anyObject())).andReturn(serviceInfo).anyTimes(); + + // replay + replay(managementController, clusters, cluster, service1, service2, + ambariMetaInfo, serviceFactory, serviceInfo, repoVersion); + + SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator()); + + Capture<Long> pkCapture = Capture.newInstance(); + ResourceProvider provider = getServiceProvider(managementController, true, pkCapture); + + // add the property map to a set for the request. add more maps for multiple creates + Set<Map<String, Object>> propertySet = new LinkedHashSet<>(); + + // Service 1: create a map of properties for the request + Map<String, Object> properties = new LinkedHashMap<>(); + + // add properties to the request map + properties.put(ServiceResourceProvider.SERVICE_CLUSTER_NAME_PROPERTY_ID, "Cluster100"); + properties.put(ServiceResourceProvider.SERVICE_SERVICE_NAME_PROPERTY_ID, "Service200"); + properties.put(ServiceResourceProvider.SERVICE_SERVICE_STATE_PROPERTY_ID, "INIT"); + properties.put(ServiceResourceProvider.SERVICE_DESIRED_STACK_PROPERTY_ID, "HDP-1.1"); + + propertySet.add(properties); + + // create the request + Request request = PropertyHelper.getCreateRequest(propertySet, null); + + provider.createResources(request); + + // verify + verify(managementController, clusters, cluster, service1, service2, + ambariMetaInfo, serviceFactory, serviceInfo); + + Assert.assertTrue(pkCapture.hasCaptured()); + Assert.assertEquals(Long.valueOf(500L), pkCapture.getValue()); + } + + @Test + public void testCreateWithNoRepositoryIdAndPatch() throws Exception { + AmbariManagementController managementController = createNiceMock(AmbariManagementController.class); + Clusters clusters = createNiceMock(Clusters.class); + Cluster cluster = createNiceMock(Cluster.class); + Service service1 = createNiceMock(Service.class); + Service service2 = createNiceMock(Service.class); + + RepositoryVersionEntity repoVersion = createNiceMock(RepositoryVersionEntity.class); + expect(repoVersion.getId()).andReturn(500L).anyTimes(); + expect(repoVersion.getParentId()).andReturn(600L).anyTimes(); + expect(repoVersion.getType()).andReturn(RepositoryType.PATCH).anyTimes(); + expect(service1.getDesiredRepositoryVersion()).andReturn(repoVersion).atLeastOnce(); + + StackId stackId = new StackId("HDP-2.5"); + ServiceFactory serviceFactory = createNiceMock(ServiceFactory.class); + AmbariMetaInfo ambariMetaInfo = createNiceMock(AmbariMetaInfo.class); + ServiceInfo serviceInfo = createNiceMock(ServiceInfo.class); + + expect(managementController.getClusters()).andReturn(clusters).anyTimes(); + expect(managementController.getAmbariMetaInfo()).andReturn(ambariMetaInfo).anyTimes(); + + expect(cluster.addService(eq("Service200"), EasyMock.anyObject(RepositoryVersionEntity.class))).andReturn(service2); + + expect(clusters.getCluster("Cluster100")).andReturn(cluster).anyTimes(); + + expect(cluster.getServices()).andReturn( + ImmutableMap.<String, Service>builder() + .put("Service100", service1).build()).atLeastOnce(); + + expect(cluster.getDesiredStackVersion()).andReturn(stackId).anyTimes(); + expect(cluster.getClusterId()).andReturn(2L).anyTimes(); + + expect(ambariMetaInfo.isValidService( (String) anyObject(), (String) anyObject(), (String) anyObject())).andReturn(true); + expect(ambariMetaInfo.getService((String)anyObject(), (String)anyObject(), (String)anyObject())).andReturn(serviceInfo).anyTimes(); + + // replay + replay(managementController, clusters, cluster, service1, service2, + ambariMetaInfo, serviceFactory, serviceInfo, repoVersion); + + SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator()); + + Capture<Long> pkCapture = Capture.newInstance(); + ResourceProvider provider = getServiceProvider(managementController, true, pkCapture); + + // add the property map to a set for the request. add more maps for multiple creates + Set<Map<String, Object>> propertySet = new LinkedHashSet<>(); + + // Service 1: create a map of properties for the request + Map<String, Object> properties = new LinkedHashMap<>(); + + // add properties to the request map + properties.put(ServiceResourceProvider.SERVICE_CLUSTER_NAME_PROPERTY_ID, "Cluster100"); + properties.put(ServiceResourceProvider.SERVICE_SERVICE_NAME_PROPERTY_ID, "Service200"); + properties.put(ServiceResourceProvider.SERVICE_SERVICE_STATE_PROPERTY_ID, "INIT"); + properties.put(ServiceResourceProvider.SERVICE_DESIRED_STACK_PROPERTY_ID, "HDP-1.1"); + + propertySet.add(properties); + + // create the request + Request request = PropertyHelper.getCreateRequest(propertySet, null); + + provider.createResources(request); + + // verify + verify(managementController, clusters, cluster, service1, service2, + ambariMetaInfo, serviceFactory, serviceInfo); + + Assert.assertTrue(pkCapture.hasCaptured()); + Assert.assertEquals(Long.valueOf(600L), pkCapture.getValue()); + } + + @Test + public void testCreateWithNoRepositoryIdAndMultiBase() throws Exception { + AmbariManagementController managementController = createNiceMock(AmbariManagementController.class); + Clusters clusters = createNiceMock(Clusters.class); + Cluster cluster = createNiceMock(Cluster.class); + Service service1 = createNiceMock(Service.class); + Service service2 = createNiceMock(Service.class); + Service service3 = createNiceMock(Service.class); + + RepositoryVersionEntity repoVersion1 = createNiceMock(RepositoryVersionEntity.class); + expect(repoVersion1.getId()).andReturn(500L).anyTimes(); + expect(service1.getDesiredRepositoryVersion()).andReturn(repoVersion1).atLeastOnce(); + + RepositoryVersionEntity repoVersion2 = createNiceMock(RepositoryVersionEntity.class); + expect(repoVersion2.getId()).andReturn(600L).anyTimes(); + expect(service2.getDesiredRepositoryVersion()).andReturn(repoVersion2).atLeastOnce(); + + StackId stackId = new StackId("HDP-2.5"); + ServiceFactory serviceFactory = createNiceMock(ServiceFactory.class); + AmbariMetaInfo ambariMetaInfo = createNiceMock(AmbariMetaInfo.class); + ServiceInfo serviceInfo = createNiceMock(ServiceInfo.class); + + expect(managementController.getClusters()).andReturn(clusters).anyTimes(); + expect(managementController.getAmbariMetaInfo()).andReturn(ambariMetaInfo).anyTimes(); + + expect(clusters.getCluster("Cluster100")).andReturn(cluster).anyTimes(); + + expect(cluster.getServices()).andReturn( + ImmutableMap.<String, Service>builder() + .put("Service100", service1) + .put("Service200", service2).build()).atLeastOnce(); + + expect(cluster.getDesiredStackVersion()).andReturn(stackId).anyTimes(); + expect(cluster.getClusterId()).andReturn(2L).anyTimes(); + + // replay + replay(managementController, clusters, cluster, service1, service2, service3, + ambariMetaInfo, serviceFactory, serviceInfo, repoVersion1, repoVersion2); + + SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator()); + + Capture<Long> pkCapture = Capture.newInstance(); + ResourceProvider provider = getServiceProvider(managementController, true, pkCapture); + + // add the property map to a set for the request. add more maps for multiple creates + Set<Map<String, Object>> propertySet = new LinkedHashSet<>(); + + // Service 1: create a map of properties for the request + Map<String, Object> properties = new LinkedHashMap<>(); + + // add properties to the request map + properties.put(ServiceResourceProvider.SERVICE_CLUSTER_NAME_PROPERTY_ID, "Cluster100"); + properties.put(ServiceResourceProvider.SERVICE_SERVICE_NAME_PROPERTY_ID, "Service200"); + properties.put(ServiceResourceProvider.SERVICE_SERVICE_STATE_PROPERTY_ID, "INIT"); + properties.put(ServiceResourceProvider.SERVICE_DESIRED_STACK_PROPERTY_ID, "HDP-1.1"); + + propertySet.add(properties); + + // create the request + Request request = PropertyHelper.getCreateRequest(propertySet, null); + + try { + provider.createResources(request); + Assert.fail("Expected an exception when more than one base version was found"); + } catch (IllegalArgumentException expected) { + // !!! expected + } + + // verify + verify(managementController, clusters, cluster, service1, service2, service3, + ambariMetaInfo, serviceFactory, serviceInfo); + + } + + private static ServiceResourceProvider getServiceProvider(AmbariManagementController managementController, + boolean mockFindByStack, Capture<Long> pkCapture) throws AmbariException { MaintenanceStateHelper maintenanceStateHelperMock = createNiceMock(MaintenanceStateHelper.class); RepositoryVersionDAO repositoryVersionDAO = createNiceMock(RepositoryVersionDAO.class); expect(maintenanceStateHelperMock.isOperationAllowed(anyObject(Resource.Type.class), anyObject(Service.class))).andReturn(true).anyTimes(); @@ -1158,7 +1378,11 @@ public class ServiceResourceProviderTest { if (mockFindByStack) { RepositoryVersionEntity repositoryVersion = createNiceMock(RepositoryVersionEntity.class); - expect(repositoryVersionDAO.findByPK(EasyMock.anyLong())).andReturn(repositoryVersion).atLeastOnce(); + if (null != pkCapture) { + expect(repositoryVersionDAO.findByPK(capture(pkCapture))).andReturn(repositoryVersion).atLeastOnce(); + } else { + expect(repositoryVersionDAO.findByPK(EasyMock.anyLong())).andReturn(repositoryVersion).atLeastOnce(); + } expect(repositoryVersion.getStackId()).andReturn(new StackId("HDP-2.2")).anyTimes(); replay(repositoryVersion); @@ -1173,7 +1397,7 @@ public class ServiceResourceProviderTest { * It's useful in most cases (when we don't care about Maintenance State) */ public static ServiceResourceProvider getServiceProvider(AmbariManagementController managementController) throws AmbariException { - return getServiceProvider(managementController, false); + return getServiceProvider(managementController, false, null); } /**