/** * 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.stack; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.UUID; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.state.RepositoryInfo; import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.state.stack.RepositoryXml; import org.apache.ambari.server.state.stack.ServiceMetainfoXml; import org.junit.Test; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Multiset; /** * Tests for StackModule */ public class StackModuleTest { @Test public void stackServiceReposAreRead() throws Exception { StackModule sm = createStackModule("FooBar", "2.4", Optional.of(Lists.newArrayList(repoInfo("foo", "1.0.1", "http://foo.org"))), Lists.newArrayList(repoInfo("bar", "2.0.1", "http://bar.org"))); Set<String> repoIds = getIds(sm.getModuleInfo().getRepositories()); assertEquals(ImmutableSet.of("foo:1.0.1", "bar:2.0.1"), repoIds); } /** * If more add-on services define the same repo, the duplicate repo definitions should be disregarded. * @throws Exception */ @Test public void duplicateStackServiceReposAreDiscarded() throws Exception { StackModule sm = createStackModule("FooBar", "2.4", // stack repos Optional.of(Lists.newArrayList(repoInfo("StackRepoA", "1.1.1", "http://repos.org/stackrepoA"), repoInfo("StackRepoB", "2.2.2", "http://repos.org/stackrepoB"))), // stack service repos // These two should be preserved. even though duplicates, the contents are the same Lists.newArrayList(repoInfo("serviceRepoA", "1.0.0", "http://bar.org/1_0_0")), Lists.newArrayList(repoInfo("serviceRepoA", "1.0.0", "http://bar.org/1_0_0")), // These should be dropped as the names are the same but contents are different Lists.newArrayList(repoInfo("serviceRepoB", "1.2.1", "http://bar.org/1_1_1")), Lists.newArrayList(repoInfo("serviceRepoB", "1.2.3", "http://bar.org/1_1_1")), // The first one should be dropped (overrides a stack repo), the rest only generates warnings (duplicate urls) Lists.newArrayList(repoInfo("StackRepoA", "2.0.0", "http://repos.org/stackrepoA_200"), repoInfo("ShouldBeJustAWarning1", "3.1.1", "http://repos.org/stackrepoA"), repoInfo("ShouldBeJustAWarning2", "1.0.0", "http://bar.org/1_0_0"))); List<RepositoryInfo> repos = sm.getModuleInfo().getRepositories(); Set<String> repoIds = getIds(repos); assertEquals("Unexpected number of repos. Each repo should be added only once", repoIds.size(), repos.size()); assertEquals("Unexpected repositories", ImmutableSet.of("StackRepoA:1.1.1", "StackRepoB:2.2.2", "serviceRepoA:1.0.0", "ShouldBeJustAWarning1:3.1.1", "ShouldBeJustAWarning2:1.0.0"), repoIds); } @Test public void serviceReposAreProcessedEvenIfNoStackRepo() throws Exception { StackModule sm = createStackModule("FooBar", "2.4", Optional.<List<RepositoryInfo>>absent(), Lists.newArrayList(repoInfo("bar", "2.0.1", "http://bar.org"))); Set<String> repoIds = getIds(sm.getModuleInfo().getRepositories()); assertEquals(ImmutableSet.of("bar:2.0.1"), repoIds); } /** * If two add-on services define the same repo, the repo should be disregarded. * This applies per os, so the same repo can be defined for multiple os'es (e.g redhat5 and redhat6) * @throws Exception */ @Test public void duplicateStackServiceReposAreCheckedPerOs() throws Exception { StackModule sm = createStackModule("FooBar", "2.4", Optional.<List<RepositoryInfo>>absent(), Lists.newArrayList(repoInfo("bar", "2.0.1", "http://bar.org", "centos6")), Lists.newArrayList(repoInfo("bar", "2.0.1", "http://bar.org", "centos7"))); Multiset<String> repoIds = getIdsMultiple(sm.getModuleInfo().getRepositories()); assertEquals("Repo should be occur exactly twice, once for each os type.", ImmutableMultiset.of("bar:2.0.1", "bar:2.0.1"), repoIds); } @Test public void removedServicesInitialValue () throws Exception { StackModule sm = createStackModule("FooBar", "2.4", Optional.<List<RepositoryInfo>>absent(), Lists.newArrayList(repoInfo("bar", "2.0.1", "http://bar.org", "centos6")), Lists.newArrayList(repoInfo("bar", "2.0.1", "http://bar.org", "centos7"))); List<String> removedServices = sm.getModuleInfo().getRemovedServices(); assertEquals(removedServices.size(), 0); } @Test public void servicesWithNoConfigsInitialValue() throws Exception { StackModule sm = createStackModule("FooBar", "2.4", Optional.<List<RepositoryInfo>>absent(), Lists.newArrayList(repoInfo("bar", "2.0.1", "http://bar.org", "centos6")), Lists.newArrayList(repoInfo("bar", "2.0.1", "http://bar.org", "centos7"))); List<String> servicesWithNoConfigs = sm.getModuleInfo().getServicesWithNoConfigs(); assertEquals(servicesWithNoConfigs.size(), 0); } @SafeVarargs private static StackModule createStackModule(String stackName, String stackVersion, Optional<? extends List<RepositoryInfo>> stackRepos, List<RepositoryInfo>... serviceRepoLists) throws AmbariException { StackDirectory sd = mock(StackDirectory.class); List<ServiceDirectory> serviceDirectories = Lists.newArrayList(); for (List<RepositoryInfo> serviceRepoList: serviceRepoLists) { StackServiceDirectory svd = mock(StackServiceDirectory.class); RepositoryXml serviceRepoXml = mock(RepositoryXml.class); when(svd.getRepoFile()).thenReturn(serviceRepoXml); when(serviceRepoXml.getRepositories()).thenReturn(serviceRepoList); ServiceMetainfoXml serviceMetainfoXml = mock(ServiceMetainfoXml.class); when(serviceMetainfoXml.isValid()).thenReturn(true); ServiceInfo serviceInfo = mock(ServiceInfo.class); when(serviceInfo.isValid()).thenReturn(true); when(serviceInfo.getName()).thenReturn(UUID.randomUUID().toString()); // unique service names when(serviceMetainfoXml.getServices()).thenReturn(Lists.newArrayList(serviceInfo)); when(svd.getMetaInfoFile()).thenReturn(serviceMetainfoXml); serviceDirectories.add(svd); } if (stackRepos.isPresent()) { RepositoryXml stackRepoXml = mock(RepositoryXml.class); when(sd.getRepoFile()).thenReturn(stackRepoXml); when(stackRepoXml.getRepositories()).thenReturn(stackRepos.get()); } when(sd.getServiceDirectories()).thenReturn(serviceDirectories); when(sd.getStackDirName()).thenReturn(stackName); when(sd.getDirectory()).thenReturn(new File(stackVersion)); StackContext ctx = mock(StackContext.class); StackModule sm = new StackModule(sd, ctx); sm.resolve(null, ImmutableMap.of(String.format("%s:%s", stackName, stackVersion), sm), ImmutableMap.<String, ServiceModule>of(), ImmutableMap.<String, ExtensionModule>of()); return sm; } private RepositoryInfo repoInfo(String repoName, String repoVersion, String url) { return repoInfo(repoName, repoVersion, url, "centos6"); } private List<RepositoryInfo> repoInfosForAllOs(String repoName, String repoVersion, String url) { List<RepositoryInfo> repos = new ArrayList<>(3); for (String os: new String[]{ "centos5", "centos6", "centos7"}) { repos.add(repoInfo(repoName, repoVersion, url, os)); } return repos; } private RepositoryInfo repoInfo(String repoName, String repoVersion, String url, String osType) { RepositoryInfo info = new RepositoryInfo(); info.setRepoId(String.format("%s:%s", repoName, repoVersion)); info.setRepoName(repoName); info.setBaseUrl(url); info.setOsType(osType); return info; } private Set<String> getIds(List<RepositoryInfo> repoInfos) { return ImmutableSet.copyOf(Lists.transform(repoInfos, RepositoryInfo.GET_REPO_ID_FUNCTION)); } private Multiset<String> getIdsMultiple(List<RepositoryInfo> repoInfos) { return ImmutableMultiset.copyOf(Lists.transform(repoInfos, RepositoryInfo.GET_REPO_ID_FUNCTION)); } }