AMBARI-20871. Unify repository file creation (ncole)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b6866249 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b6866249 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b6866249 Branch: refs/heads/branch-feature-AMBARI-12556 Commit: b68662490a64277f4d5eb7ae18b54850678deff2 Parents: 13d806b Author: Nate Cole <nc...@hortonworks.com> Authored: Thu Apr 27 10:15:29 2017 -0400 Committer: Nate Cole <nc...@hortonworks.com> Committed: Thu Apr 27 16:11:15 2017 -0400 ---------------------------------------------------------------------- .../libraries/functions/repository_util.py | 127 ++ .../ambari/server/agent/CommandRepository.java | 170 +++ .../ambari/server/agent/ExecutionCommand.java | 32 +- .../commands/StackAdvisorCommand.java | 6 +- .../DistributeRepositoriesStructuredOutput.java | 12 - .../controller/ActionExecutionContext.java | 35 + .../controller/AmbariActionExecutionHelper.java | 2 + .../AmbariCustomCommandExecutionHelper.java | 222 ++- .../AmbariManagementControllerImpl.java | 4 +- .../ClusterStackVersionResourceProvider.java | 105 +- .../HostStackVersionResourceProvider.java | 70 +- .../stack/upgrade/RepositoryVersionHelper.java | 130 +- .../custom_actions/scripts/install_packages.py | 63 +- .../hooks/before-INSTALL/scripts/params.py | 2 + .../scripts/repo_initialization.py | 22 +- ...ClusterStackVersionResourceProviderTest.java | 19 +- .../HostStackVersionResourceProviderTest.java | 3 +- .../upgrades/UpgradeActionTest.java | 15 +- .../UpdateActiveRepoVersionOnStartupTest.java | 25 +- .../upgrade/RepositoryVersionHelperTest.java | 27 +- .../custom_actions/TestInstallPackages.py | 118 +- .../install_packages_repository_file.json | 112 ++ .../stacks/2.0.6/configs/repository_file.json | 1275 ++++++++++++++++++ .../hooks/before-INSTALL/test_before_install.py | 30 + 24 files changed, 2293 insertions(+), 333 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-common/src/main/python/resource_management/libraries/functions/repository_util.py ---------------------------------------------------------------------- diff --git a/ambari-common/src/main/python/resource_management/libraries/functions/repository_util.py b/ambari-common/src/main/python/resource_management/libraries/functions/repository_util.py new file mode 100644 index 0000000..c9920e2 --- /dev/null +++ b/ambari-common/src/main/python/resource_management/libraries/functions/repository_util.py @@ -0,0 +1,127 @@ +""" +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. + +""" + +from resource_management.core.exceptions import Fail +from resource_management.core.logger import Logger +from resource_management.libraries.resources.repository import Repository +import ambari_simplejson as json + + +__all__ = ["create_repo_files", "CommandRepository"] + +# components_lits = repoName + postfix +UBUNTU_REPO_COMPONENTS_POSTFIX = ["main"] + + +def create_repo_files(template, command_repository): + """ + Creates repositories in a consistent manner for all types + :param command_repository: a CommandRepository instance + :return: + """ + + if command_repository.version_id is None: + raise Fail("The command repository was not parsed correctly") + + if 0 == len(command_repository.repositories): + raise Fail("Cannot create repository files when no repositories are defined") + + # add the stack name to the file name just to make it a little easier to debug + # version_id is the primary id of the repo_version table in the database + file_name = "ambari-{0}-{1}".format(command_repository.stack_name.lower(), + command_repository.version_id) + + append_to_file = False # initialize to False to create the file anew. + + for repository in command_repository.repositories: + + if repository.repo_id is None: + raise Fail("Repository with url {0} has no id".format(repository.base_url)) + + Repository(repository.repo_id, + action = "create", + base_url = repository.base_url, + mirror_list = repository.mirrors_list, + repo_file_name = file_name, + repo_template = template, + components = repository.ubuntu_components, + append_to_file = append_to_file) + append_to_file = True + + +def _find_value(dictionary, key): + """ + Helper to find a value in a dictionary + """ + if key not in dictionary: + return None + + return dictionary[key] + + +class CommandRepository(object): + """ + Class that encapsulates the representation of repositories passed in a command. This class + should match the CommandRepository class. + """ + + def __init__(self, jsonvalue): + + if isinstance(jsonvalue, dict): + json_dict = jsonvalue + elif isinstance(jsonvalue, basestring): + json_dict = json.loads(jsonvalue) + + if json_dict is None: + raise Fail("Cannot deserialize command repository {0}".format(str(jsonvalue))) + + # version_id is the primary id of the repo_version table in the database + self.version_id = _find_value(json_dict, 'repoVersionId') + self.stack_name = _find_value(json_dict, 'stackName') + self.repositories = [] + + repos_def = _find_value(json_dict, 'repositories') + if repos_def is not None: + if not isinstance(repos_def, list): + repos_def = [repos_def] + + for repo_def in repos_def: + self.repositories.append(_CommandRepositoryEntry(repo_def)) + + +class _CommandRepositoryEntry(object): + """ + Class that represents the entries of a CommandRepository. This isn't meant to be instantiated + outside a CommandRepository + """ + def __init__(self, json_dict): + self.repo_id = _find_value(json_dict, 'repoId') # this is the id within the repo file, not an Ambari artifact + self.repo_name = _find_value(json_dict, 'repoName') + self.base_url = _find_value(json_dict, 'baseUrl') + self.mirrors_list = _find_value(json_dict, 'mirrorsList') + + # if repoName is changed on the java side, this will fail for ubuntu since we rely on the + # name being the same as how the repository was built + self.ubuntu_components = [self.repo_name] + UBUNTU_REPO_COMPONENTS_POSTFIX + + + + + + http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandRepository.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandRepository.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandRepository.java new file mode 100644 index 0000000..849d6fb --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandRepository.java @@ -0,0 +1,170 @@ +/** + * 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.agent; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.ambari.server.orm.entities.RepositoryEntity; +import org.apache.ambari.server.state.RepositoryInfo; + +import com.google.gson.annotations.SerializedName; + +/** + * Wraps the information required to create repositories from a command. This was added + * as a top level command object. + */ +public class CommandRepository { + + @SerializedName("repositories") + private List<Repository> m_repositories = new ArrayList<>(); + + @SerializedName("repoVersion") + private String m_repoVersion; + + @SerializedName("repoVersionId") + private long m_repoVersionId; + + @SerializedName("stackName") + private String m_stackName; + + /** + * @param version the repo version + */ + public void setRepositoryVersion(String version) { + m_repoVersion = version; + } + + /** + * @param id the repository id + */ + public void setRepositoryVersionId(long id) { + m_repoVersionId = id; + } + + /** + * @param name the stack name + */ + public void setStackName(String name) { + m_stackName = name; + } + + /** + * @param repositories the repositories if sourced from the stack instead of the repo_version. + */ + public void setRepositories(Collection<RepositoryInfo> repositories) { + m_repositories = new ArrayList<>(); + + for (RepositoryInfo info : repositories) { + m_repositories.add(new Repository(info)); + } + } + + /** + * @param osType the OS type for the repositories + * @param repositories the repository entities that should be processed into a file + */ + public void setRepositories(String osType, Collection<RepositoryEntity> repositories) { + m_repositories = new ArrayList<>(); + + for (RepositoryEntity entity : repositories) { + m_repositories.add(new Repository(osType, entity)); + } + } + + /** + * @return the repositories that the command should process into a file. + */ + public Collection<Repository> getRepositories() { + return m_repositories; + } + + /** + * Sets a uniqueness on the repo ids. + * + * @param suffix the repo id suffix + */ + public void setUniqueSuffix(String suffix) { + for (Repository repo : m_repositories) { + repo.m_repoId = repo.m_repoId + suffix; + } + } + + /** + * Minimal information required to generate repo files on the agent. These are copies + * of the repository objects from repo versions that can be changed for URL overrides, etc. + */ + public static class Repository { + + @SerializedName("baseUrl") + private String m_baseUrl; + + @SerializedName("repoId") + private String m_repoId; + + /** + * The name should not change. Ubuntu requires that it match exactly as the repo was built. + */ + @SerializedName("repoName") + private final String m_repoName; + + @SerializedName("mirrorsList") + private String m_mirrorsList; + + private transient String m_osType; + + private Repository(RepositoryInfo info) { + m_baseUrl = info.getBaseUrl(); + m_osType = info.getOsType(); + m_repoId = info.getRepoId(); + m_repoName = info.getRepoName(); + m_mirrorsList = info.getMirrorsList(); + } + + private Repository(String osType, RepositoryEntity entity) { + m_baseUrl = entity.getBaseUrl(); + m_repoId = entity.getRepositoryId(); + m_repoName = entity.getName(); + m_mirrorsList = entity.getMirrorsList(); + m_osType = osType; + } + + public void setBaseUrl(String url) { + m_baseUrl = url; + } + + public String getOsType() { + return m_osType; + } + + public String getRepoId() { + return m_repoId; + } + + public String getRepoName() { + return m_repoName; + } + + + public String getBaseUrl() { + return m_baseUrl; + } + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java index 8c726a0..bd62cbb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java @@ -24,6 +24,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.ambari.annotations.Experimental; +import org.apache.ambari.annotations.ExperimentalFeature; import org.apache.ambari.server.RoleCommand; import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.utils.StageUtils; @@ -76,8 +78,7 @@ public class ExecutionCommand extends AgentCommand { private RoleCommand roleCommand; @SerializedName("clusterHostInfo") - private Map<String, Set<String>> clusterHostInfo = - new HashMap<>(); + private Map<String, Set<String>> clusterHostInfo = new HashMap<>(); @SerializedName("configurations") private Map<String, Map<String, String>> configurations; @@ -144,6 +145,14 @@ public class ExecutionCommand extends AgentCommand { @SerializedName("configuration_credentials") private Map<String, Map<String, String>> configurationCredentials; + + /** + * Provides information regarding the content of repositories. This structure replaces + * the deprecated use of {@link KeyNames#REPO_INFO} + */ + @SerializedName("repositoryFile") + private CommandRepository commandRepository; + public void setConfigurationCredentials(Map<String, Map<String, String>> configurationCredentials) { this.configurationCredentials = configurationCredentials; } @@ -395,6 +404,20 @@ public class ExecutionCommand extends AgentCommand { } /** + * @return the repository file that is to be written. + */ + public CommandRepository getRepositoryFile() { + return commandRepository; + } + + /** + * @param repository the command repository instance. + */ + public void setRepositoryFile(CommandRepository repository) { + commandRepository = repository; + } + + /** * Contains key name strings. These strings are used inside maps * incapsulated inside command. */ @@ -420,6 +443,11 @@ public class ExecutionCommand extends AgentCommand { String ORACLE_JDBC_URL = "oracle_jdbc_url"; String DB_DRIVER_FILENAME = "db_driver_filename"; String CLIENTS_TO_UPDATE_CONFIGS = "clientsToUpdateConfigs"; + /** + * Keep for backward compatibility. + */ + @Deprecated + @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES) String REPO_INFO = "repo_info"; String DB_NAME = "db_name"; String GLOBAL = "global"; http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java index 74a2cf2..a291a88 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java @@ -348,13 +348,13 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend return file.isDirectory() && !FileUtils.isFileNewer(file, cutoffDate); } }); - + if(oldDirectories.length > 0) { LOG.info(String.format("Deleting old directories %s from %s", StringUtils.join(oldDirectories, ", "), recommendationsDir)); } - + for(String oldDirectory:oldDirectories) { - FileUtils.deleteDirectory(new File(recommendationsDir, oldDirectory)); + FileUtils.deleteQuietly(new File(recommendationsDir, oldDirectory)); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/java/org/apache/ambari/server/bootstrap/DistributeRepositoriesStructuredOutput.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/bootstrap/DistributeRepositoriesStructuredOutput.java b/ambari-server/src/main/java/org/apache/ambari/server/bootstrap/DistributeRepositoriesStructuredOutput.java index 662b856..7c961b5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/bootstrap/DistributeRepositoriesStructuredOutput.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/bootstrap/DistributeRepositoriesStructuredOutput.java @@ -19,8 +19,6 @@ package org.apache.ambari.server.bootstrap; -import java.util.List; - import com.google.gson.annotations.SerializedName; /** @@ -36,12 +34,6 @@ public class DistributeRepositoriesStructuredOutput { private String installedRepositoryVersion; /** - * All Ambari-managed repositories that are installed side by side on host - */ - @SerializedName("ambari_repositories") - private List<String> ambariRepositories; - - /** * Either SUCCESS or FAIL */ @SerializedName("package_installation_result") @@ -64,10 +56,6 @@ public class DistributeRepositoriesStructuredOutput { return installedRepositoryVersion; } - public List<String> getAmbariRepositories() { - return ambariRepositories; - } - public String getPackageInstallationResult() { return packageInstallationResult; } http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java index 3681eda..5566fe2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java @@ -19,10 +19,12 @@ package org.apache.ambari.server.controller; +import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.ambari.server.actionmanager.TargetHostType; +import org.apache.ambari.server.agent.ExecutionCommand; import org.apache.ambari.server.controller.internal.RequestOperationLevel; import org.apache.ambari.server.controller.internal.RequestResourceFilter; @@ -42,6 +44,8 @@ public class ActionExecutionContext { private boolean hostsInMaintenanceModeExcluded = true; private boolean allowRetry = false; + private List<ExecutionCommandVisitor> m_visitors = new ArrayList<>(); + /** * {@code true} if slave/client component failures should be automatically * skipped. This will only automatically skip the failure if the task is @@ -168,6 +172,16 @@ public class ActionExecutionContext { this.autoSkipFailures = autoSkipFailures; } + /** + * Adds a command visitor that will be invoked after a command is created. Provides access + * to the command. + * + * @param visitor the visitor + */ + public void addVisitor(ExecutionCommandVisitor visitor) { + m_visitors.add(visitor); + } + @Override public String toString() { return "ActionExecutionContext{" + @@ -207,4 +221,25 @@ public class ActionExecutionContext { hostsInMaintenanceModeExcluded = excluded; } + /** + * Called as a way to post-process the command after it has been created and various objects + * have been set. + * + * @param command the command + */ + public void visitAll(ExecutionCommand command) { + for (ExecutionCommandVisitor visitor : m_visitors) { + visitor.visit(command); + } + } + + /** + * Interface that allows a final attempt to setting values on an {@link ExecutionCommand} + * @author ncole + * + */ + public static interface ExecutionCommandVisitor { + public void visit(ExecutionCommand command); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java index d556b60..835d607 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java @@ -487,6 +487,8 @@ public class AmbariActionExecutionHelper { execCmd.getLocalComponents().add(sch.getServiceComponentName()); } } + + actionContext.visitAll(execCmd); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java index ab8b659..d6905fb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java @@ -58,6 +58,8 @@ import java.util.Random; import java.util.Set; import java.util.TreeMap; +import org.apache.ambari.annotations.Experimental; +import org.apache.ambari.annotations.ExperimentalFeature; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.Role; import org.apache.ambari.server.RoleCommand; @@ -65,6 +67,7 @@ import org.apache.ambari.server.actionmanager.HostRoleCommand; import org.apache.ambari.server.actionmanager.HostRoleStatus; import org.apache.ambari.server.actionmanager.Stage; import org.apache.ambari.server.agent.AgentCommand.AgentCommandType; +import org.apache.ambari.server.agent.CommandRepository; import org.apache.ambari.server.agent.ExecutionCommand; import org.apache.ambari.server.agent.ExecutionCommand.KeyNames; import org.apache.ambari.server.api.services.AmbariMetaInfo; @@ -108,6 +111,7 @@ import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Function; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -500,6 +504,8 @@ public class AmbariCustomCommandExecutionHelper { execCmd.setCommandParams(commandParams); execCmd.setRoleParams(roleParams); + execCmd.setRepositoryFile(getCommandRepository(cluster, host)); + // perform any server side command related logic - eg - set desired states on restart applyCustomCommandBackendLogic(cluster, serviceName, componentName, commandName, hostName); } @@ -1169,54 +1175,186 @@ public class AmbariCustomCommandExecutionHelper { * * @return the repo info * + * @deprecated use {@link #getCommandRepository(Cluster, Host)} instead. * @throws AmbariException if the repository information can not be obtained */ + @Deprecated public String getRepoInfo(Cluster cluster, Host host) throws AmbariException { - return getRepoInfo(cluster, host.getOsType(), host.getOsFamily(), host.getHostName()); + Function<List<RepositoryInfo>, JsonArray> function = new Function<List<RepositoryInfo>, JsonArray>() { + @Override + public JsonArray apply(List<RepositoryInfo> input) { + return null == input ? null : (JsonArray) gson.toJsonTree(input); + } + }; + + final JsonArray gsonList = getBaseUrls(cluster, host, function); + + if (null == gsonList) { + return ""; + } + + BaseUrlUpdater<JsonArray> updater = new BaseUrlUpdater<JsonArray>(gsonList) { + @Override + public JsonArray apply(final RepositoryVersionEntity rve) { + + JsonArray result = new JsonArray(); + + for (JsonElement e : gsonList) { + JsonObject obj = e.getAsJsonObject(); + + String repoId = obj.has("repoId") ? obj.get("repoId").getAsString() : null; + String repoName = obj.has("repoName") ? obj.get("repoName").getAsString() : null; + String baseUrl = obj.has("baseUrl") ? obj.get("baseUrl").getAsString() : null; + String osType = obj.has("osType") ? obj.get("osType").getAsString() : null; + + if (null == repoId || null == baseUrl || null == osType || null == repoName) { + continue; + } + + for (OperatingSystemEntity ose : rve.getOperatingSystems()) { + if (ose.getOsType().equals(osType) && ose.isAmbariManagedRepos()) { + for (RepositoryEntity re : ose.getRepositories()) { + if (re.getName().equals(repoName) && + re.getRepositoryId().equals(repoId) && + !re.getBaseUrl().equals(baseUrl)) { + obj.addProperty("baseUrl", re.getBaseUrl()); + } + } + result.add(e); + } + } + } + + return result; + } + }; + + return updateBaseUrls(cluster, updater).toString(); + } + + /** + * Builds repository information for inclusion in a command. This replaces escaping json on + * a command. + * + * @param cluster the cluster + * @param host the host + * @return the command repository + * @throws AmbariException + */ + @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES) + public CommandRepository getCommandRepository(final Cluster cluster, Host host) throws AmbariException { + + Function<List<RepositoryInfo>, List<RepositoryInfo>> function = new Function<List<RepositoryInfo>, List<RepositoryInfo>>() { + @Override + public List<RepositoryInfo> apply(List<RepositoryInfo> input) { + // !!! just return what is given + return input; + } + }; + + final List<RepositoryInfo> repoInfos = getBaseUrls(cluster, host, function); + + if (null == repoInfos) { + return null; + } + + final CommandRepository command = new CommandRepository(); + StackId stackId = cluster.getDesiredStackVersion(); + command.setRepositories(repoInfos); + command.setStackName(stackId.getStackName()); + + final BaseUrlUpdater<Void> updater = new BaseUrlUpdater<Void>(null) { + @Override + public Void apply(RepositoryVersionEntity rve) { + + command.setRepositoryVersionId(rve.getId()); + command.setRepositoryVersion(rve.getVersion()); + command.setStackName(rve.getStackName()); + command.setUniqueSuffix(String.format("-repo-%s", rve.getId())); + + for (CommandRepository.Repository commandRepo : command.getRepositories()) { + String osType = commandRepo.getOsType(); + String repoId = commandRepo.getRepoId(); + String repoName = commandRepo.getRepoName(); + String baseUrl = commandRepo.getBaseUrl(); + + for (OperatingSystemEntity ose : rve.getOperatingSystems()) { + if (ose.getOsType().equals(osType) && ose.isAmbariManagedRepos()) { + for (RepositoryEntity re : ose.getRepositories()) { + if (re.getName().equals(repoName) && + re.getRepositoryId().equals(repoId) && + !re.getBaseUrl().equals(baseUrl)) { + commandRepo.setBaseUrl(re.getBaseUrl()); + } + } + } + } + } + + return null; + } + }; + + updateBaseUrls(cluster, updater); + + return command; } - public String getRepoInfo(Cluster cluster, String hostOSType, String hostOSFamily, String hostName) throws AmbariException { + /** + * Executed by two different representations of repos. When we are comfortable with the new + * implemenation, this may be removed and called inline in {@link #getCommandRepository(Cluster, Host)} + * + * @param cluster the cluster to isolate the stack + * @param host used to resolve the family for the repositories + * @param function function that will transform the supplied repositories for specific use. + * @return <T> the type as defined by the supplied {@code function}. + * @throws AmbariException + */ + @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES) + private <T> T getBaseUrls(Cluster cluster, Host host, Function<List<RepositoryInfo>, T> function) throws AmbariException { + + String hostOsType = host.getOsType(); + String hostOsFamily = host.getOsFamily(); + String hostName = host.getHostName(); StackId stackId = cluster.getDesiredStackVersion(); Map<String, List<RepositoryInfo>> repos = ambariMetaInfo.getRepository( stackId.getStackName(), stackId.getStackVersion()); - String family = os_family.find(hostOSType); + String family = os_family.find(hostOsType); if (null == family) { - family = hostOSFamily; + family = hostOsFamily; } - JsonElement gsonList = null; + final List<RepositoryInfo> repoInfos; // !!! check for the most specific first - if (repos.containsKey(hostOSType)) { - gsonList = gson.toJsonTree(repos.get(hostOSType)); + if (repos.containsKey(hostOsType)) { + repoInfos = repos.get(hostOsType); } else if (null != family && repos.containsKey(family)) { - gsonList = gson.toJsonTree(repos.get(family)); + repoInfos = repos.get(family); } else { + repoInfos = null; LOG.warn("Could not retrieve repo information for host" + ", hostname=" + hostName + ", clusterName=" + cluster.getClusterName() + ", stackInfo=" + stackId.getStackId()); } - if (null != gsonList) { - gsonList = updateBaseUrls(cluster, JsonArray.class.cast(gsonList)); - return gsonList.toString(); - } else { - return ""; - } + // leave it to function implementation to handle null. + return function.apply(repoInfos); } /** * Checks repo URLs against the current version for the cluster and makes * adjustments to the Base URL when the current is different. - * @param cluster the cluster to load the current version - * @param jsonArray the array containing stack repo data + * + * @param <T> the result after appling the repository version, if found. */ - private JsonArray updateBaseUrls(Cluster cluster, JsonArray jsonArray) throws AmbariException { + @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES) + private <T> T updateBaseUrls(Cluster cluster, BaseUrlUpdater<T> function) throws AmbariException { ClusterVersionEntity cve = cluster.getCurrentClusterVersion(); if (null == cve) { @@ -1235,40 +1373,12 @@ public class AmbariCustomCommandExecutionHelper { if (null == cve || null == cve.getRepositoryVersion()) { LOG.info("Cluster {} has no specific Repository Versions. Using stack-defined values", cluster.getClusterName()); - return jsonArray; + return function.getDefault(); } RepositoryVersionEntity rve = cve.getRepositoryVersion(); - JsonArray result = new JsonArray(); - - for (JsonElement e : jsonArray) { - JsonObject obj = e.getAsJsonObject(); - - String repoId = obj.has("repoId") ? obj.get("repoId").getAsString() : null; - String repoName = obj.has("repoName") ? obj.get("repoName").getAsString() : null; - String baseUrl = obj.has("baseUrl") ? obj.get("baseUrl").getAsString() : null; - String osType = obj.has("osType") ? obj.get("osType").getAsString() : null; - - if (null == repoId || null == baseUrl || null == osType || null == repoName) { - continue; - } - - for (OperatingSystemEntity ose : rve.getOperatingSystems()) { - if (ose.getOsType().equals(osType) && ose.isAmbariManagedRepos()) { - for (RepositoryEntity re : ose.getRepositories()) { - if (re.getName().equals(repoName) && - re.getRepositoryId().equals(repoId) && - !re.getBaseUrl().equals(baseUrl)) { - obj.addProperty("baseUrl", re.getBaseUrl()); - } - } - result.add(e); - } - } - } - - return result; + return function.apply(rve); } @@ -1488,4 +1598,22 @@ public class AmbariCustomCommandExecutionHelper { hosts.removeAll(removedHosts); return removedHosts; } + + /** + * Class that is used to update base urls. There are two implementations of this - when we no + * longer are sure the deprecated repo info can be removed, so too can this class. + */ + @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES) + abstract static class BaseUrlUpdater<T> implements Function<RepositoryVersionEntity, T> { + private T m_default; + + private BaseUrlUpdater(T defaultValue) { + m_default = defaultValue; + } + + private T getDefault() { + return m_default; + } + + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java index 751ce08..04b72ea 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java @@ -2356,7 +2356,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle commandParams.put(ExecutionCommand.KeyNames.REFRESH_TOPOLOGY, "True"); } - String repoInfo = customCommandExecutionHelper.getRepoInfo(cluster, hostEntity.getOsType(), osFamily , hostname); + String repoInfo = customCommandExecutionHelper.getRepoInfo(cluster, host); if (LOG.isDebugEnabled()) { LOG.debug("Sending repo information to agent" + ", hostname=" + scHost.getHostName() @@ -2472,7 +2472,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle execCmd.setCommandParams(commandParams); execCmd.setAvailableServicesFromServiceInfoMap(ambariMetaInfo.getServices(stackId.getStackName(), stackId.getStackVersion())); - + execCmd.setRepositoryFile(customCommandExecutionHelper.getCommandRepository(cluster, host)); if ((execCmd != null) && (execCmd.getConfigurationTags().containsKey("cluster-env"))) { LOG.debug("AmbariManagementControllerImpl.createHostAction: created ExecutionCommand for host {}, role {}, roleCommand {}, and command ID {}, with cluster-env tags {}", http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/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 e39588e..c3e66fc 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 @@ -29,6 +29,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.ambari.annotations.Experimental; +import org.apache.ambari.annotations.ExperimentalFeature; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.Role; import org.apache.ambari.server.StaticallyInject; @@ -41,7 +43,6 @@ import org.apache.ambari.server.actionmanager.Stage; import org.apache.ambari.server.actionmanager.StageFactory; import org.apache.ambari.server.agent.CommandReport; import org.apache.ambari.server.agent.ExecutionCommand; -import org.apache.ambari.server.agent.ExecutionCommand.KeyNames; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.controller.ActionExecutionContext; @@ -79,10 +80,9 @@ import org.apache.ambari.server.state.Host; import org.apache.ambari.server.state.RepositoryType; import org.apache.ambari.server.state.RepositoryVersionState; 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.repository.VersionDefinitionXml; +import org.apache.ambari.server.state.stack.upgrade.RepositoryVersionHelper; import org.apache.ambari.server.utils.StageUtils; import org.apache.ambari.server.utils.VersionUtils; import org.apache.commons.lang.StringUtils; @@ -91,7 +91,6 @@ import org.apache.hadoop.metrics2.sink.relocated.google.common.collect.Lists; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; -import com.google.gson.Gson; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Provider; @@ -126,7 +125,7 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou protected static final String CLUSTER_STACK_VERSION_FORCE = "ClusterStackVersions/force"; protected static final String INSTALL_PACKAGES_ACTION = "install_packages"; - protected static final String INSTALL_PACKAGES_FULL_NAME = "Install version"; + protected static final String INSTALL_PACKAGES_FULL_NAME = "Install Version"; /** * The default success factor that will be used when determining if a stage's @@ -173,9 +172,6 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou private static HostRoleCommandFactory hostRoleCommandFactory; @Inject - private static Gson gson; - - @Inject private static Provider<AmbariActionExecutionHelper> actionExecutionHelper; @Inject @@ -193,6 +189,9 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou @Inject private static HostComponentStateDAO hostComponentStateDAO; + @Inject + private static RepositoryVersionHelper repoVersionHelper; + /** * We have to include such a hack here, because if we * make finalizeUpgradeAction field static and request injection @@ -602,6 +601,7 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou throws SystemException { // Determine repositories for host String osFamily = host.getOsFamily(); + final List<RepositoryEntity> repoInfo = perOsRepos.get(osFamily); if (repoInfo == null) { throw new SystemException(String.format("Repositories for os type %s are " + @@ -614,7 +614,6 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou } // determine packages for all services that are installed on host - List<ServiceOsSpecific.Package> packages = new ArrayList<>(); Set<String> servicesOnHost = new HashSet<>(); List<ServiceComponentHost> components = cluster.getServiceComponentHosts(host.getHostName()); for (ServiceComponentHost component : components) { @@ -627,65 +626,9 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou return null; } - List<String> blacklistedPackagePrefixes = configuration.getRollingUpgradeSkipPackagesPrefixes(); - for (String serviceName : servicesOnHost) { - try{ - if(ami.isServiceRemovedInStack(stackId.getStackName(), stackId.getStackVersion(), serviceName)){ - LOG.info(String.format("%s has been removed from stack %s-%s. Skip calculating its installation packages", stackId.getStackName(), stackId.getStackVersion(), serviceName)); - continue; //No need to calculate install packages for removed services - } - } catch (AmbariException e1) { - throw new SystemException(String.format("Cannot obtain stack information for %s-%s", stackId.getStackName(), stackId.getStackVersion()), e1); - } - - ServiceInfo info; - try { - info = ami.getService(stackId.getStackName(), stackId.getStackVersion(), serviceName); - } catch (AmbariException e) { - throw new SystemException("Cannot enumerate services", e); - } - - List<ServiceOsSpecific.Package> packagesForService = managementController.getPackagesForServiceHost(info, - new HashMap<String, String>(), // Contents are ignored - osFamily); - for (ServiceOsSpecific.Package aPackage : packagesForService) { - if (! aPackage.getSkipUpgrade()) { - boolean blacklisted = false; - for(String prefix : blacklistedPackagePrefixes) { - if (aPackage.getName().startsWith(prefix)) { - blacklisted = true; - break; - } - } - if (! blacklisted) { - packages.add(aPackage); - } - } - } - } - - final String packageList = gson.toJson(packages); - final String repoList = gson.toJson(repoInfo); - - Map<String, String> params = new HashMap<>(); - params.put("stack_id", stackId.getStackId()); - params.put("repository_version", repoVersion.getVersion()); - params.put("base_urls", repoList); - params.put(KeyNames.PACKAGE_LIST, packageList); - params.put(KeyNames.REPO_VERSION_ID, repoVersion.getId().toString()); - - VersionDefinitionXml xml = null; - try { - xml = repoVersion.getRepositoryXml(); - } catch (Exception e) { - throw new SystemException(String.format("Could not load xml from repo version %s", - repoVersion.getVersion())); - } - - if (null != xml && StringUtils.isNotBlank(xml.getPackageVersion(osFamily))) { - params.put(KeyNames.PACKAGE_VERSION, xml.getPackageVersion(osFamily)); - } + Map<String, String> roleParams = repoVersionHelper.buildRoleParams(managementController, repoVersion, + osFamily, servicesOnHost); // add host to this stage RequestResourceFilter filter = new RequestResourceFilter(null, null, @@ -694,9 +637,11 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou ActionExecutionContext actionContext = new ActionExecutionContext( cluster.getClusterName(), INSTALL_PACKAGES_ACTION, Collections.singletonList(filter), - params); + roleParams); actionContext.setTimeout(Short.valueOf(configuration.getDefaultAgentTaskTimeout(true))); + repoVersionHelper.addCommandRepository(actionContext, osFamily, repoVersion, repoInfo); + return actionContext; } @@ -734,29 +679,6 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou return false; } - - /** - * Sets host versions states to not-required. - * - * Transitioning host version to NOT_REQUIRED state manually is ok since - * other completion handlers set success/fail states correctly during heartbeat. - * The number of NOT_REQUIRED components for a cluster will be low. - */ - private void transitionHostVersionToNotRequired(Host host, Cluster cluster, RepositoryVersionEntity repoVersion) { - LOG.info(String.format("Transitioning version %s on host %s directly to %s" + - " without distributing bits to host since it has no versionable components.", - repoVersion.getVersion(), host.getHostName(), RepositoryVersionState.NOT_REQUIRED)); - - for (HostVersionEntity hve : host.getAllHostVersions()) { - if (hve.getRepositoryVersion().equals(repoVersion)) { - hve.setState(RepositoryVersionState.NOT_REQUIRED); - hostVersionDAO.merge(hve); - } - } - - } - - private RequestStageContainer createRequest() { ActionManager actionManager = getManagementController().getActionManager(); @@ -876,6 +798,7 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou // !!! revisit for PU // If forcing to become CURRENT, get the Cluster Version whose state is CURRENT and make sure that // the Host Version records for the same Repo Version are also marked as CURRENT. + @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES) ClusterVersionEntity current = cluster.getCurrentClusterVersion(); if (!current.getRepositoryVersion().equals(rve)) { http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProvider.java index 811ce9b..71b9b6b 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProvider.java @@ -19,7 +19,6 @@ 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.Collections; import java.util.HashMap; import java.util.HashSet; @@ -34,7 +33,6 @@ import org.apache.ambari.server.actionmanager.ActionManager; import org.apache.ambari.server.actionmanager.RequestFactory; import org.apache.ambari.server.actionmanager.Stage; import org.apache.ambari.server.actionmanager.StageFactory; -import org.apache.ambari.server.agent.ExecutionCommand.KeyNames; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.controller.ActionExecutionContext; @@ -61,17 +59,14 @@ import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Host; import org.apache.ambari.server.state.RepositoryVersionState; 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.repository.VersionDefinitionXml; +import org.apache.ambari.server.state.stack.upgrade.RepositoryVersionHelper; import org.apache.ambari.server.utils.StageUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import com.google.common.collect.Sets; -import com.google.gson.Gson; import com.google.inject.Inject; import com.google.inject.Provider; @@ -107,7 +102,7 @@ public class HostStackVersionResourceProvider extends AbstractControllerResource protected static final String INSTALL_PACKAGES_ACTION = "install_packages"; protected static final String STACK_SELECT_ACTION = "ru_set_all"; - protected static final String INSTALL_PACKAGES_FULL_NAME = "Install version"; + protected static final String INSTALL_PACKAGES_FULL_NAME = "Install Version"; private static Set<String> pkPropertyIds = Sets.newHashSet( @@ -147,8 +142,6 @@ public class HostStackVersionResourceProvider extends AbstractControllerResource @Inject private static RepositoryVersionDAO repositoryVersionDAO; - private static Gson gson = StageUtils.getGson(); - @Inject private static StageFactory stageFactory; @@ -161,6 +154,8 @@ public class HostStackVersionResourceProvider extends AbstractControllerResource @Inject private static Configuration configuration; + @Inject + private static RepositoryVersionHelper repoVersionHelper; /** * Constructor. @@ -403,8 +398,6 @@ public class HostStackVersionResourceProvider extends AbstractControllerResource LOG.error(String.format("Repository list is empty. Ambari may not be managing the repositories for %s", osFamily)); } - // For every host at cluster, determine packages for all installed services - List<ServiceOsSpecific.Package> packages = new ArrayList<>(); Set<String> servicesOnHost = new HashSet<>(); if (forceInstallOnNonMemberHost) { @@ -426,7 +419,6 @@ public class HostStackVersionResourceProvider extends AbstractControllerResource LOG.error("Service not found for component {}!", componentName, e); throw new IllegalArgumentException("Service not found for component : " + componentName); } - } } else { @@ -435,53 +427,9 @@ public class HostStackVersionResourceProvider extends AbstractControllerResource servicesOnHost.add(component.getServiceName()); } } - List<String> blacklistedPackagePrefixes = configuration.getRollingUpgradeSkipPackagesPrefixes(); - for (String serviceName : servicesOnHost) { - ServiceInfo info; - try { - info = ami.getService(stackName, stackVersion, serviceName); - } catch (AmbariException e) { - throw new SystemException("Can not enumerate services", e); - } - List<ServiceOsSpecific.Package> packagesForService = managementController.getPackagesForServiceHost(info, - new HashMap<String, String>(), // Contents are ignored - osFamily); - for (ServiceOsSpecific.Package aPackage : packagesForService) { - if (! aPackage.getSkipUpgrade()) { - boolean blacklisted = false; - for(String prefix : blacklistedPackagePrefixes) { - if (aPackage.getName().startsWith(prefix)) { - blacklisted = true; - break; - } - } - if (! blacklisted) { - packages.add(aPackage); - } - } - } - } - final String packageList = gson.toJson(packages); - final String repoList = gson.toJson(repoInfo); - - Map<String, String> params = new HashMap<String, String>(){{ - put("stack_id", stackId.getStackId()); - put("repository_version", desiredRepoVersion); - put("base_urls", repoList); - put(KeyNames.PACKAGE_LIST, packageList); - }}; - - VersionDefinitionXml xml = null; - try { - xml = repoVersionEnt.getRepositoryXml(); - } catch (Exception e) { - throw new SystemException(String.format("Could not load xml from repo version %s", - repoVersionEnt.getVersion())); - } - if (null != xml && StringUtils.isNotBlank(xml.getPackageVersion(osFamily))) { - params.put(KeyNames.PACKAGE_VERSION, xml.getPackageVersion(osFamily)); - } + Map<String, String> roleParams = repoVersionHelper.buildRoleParams(managementController, repoVersionEnt, + osFamily, servicesOnHost); // Create custom action RequestResourceFilter filter = new RequestResourceFilter(null, null, @@ -490,9 +438,11 @@ public class HostStackVersionResourceProvider extends AbstractControllerResource ActionExecutionContext actionContext = new ActionExecutionContext( cluster.getClusterName(), INSTALL_PACKAGES_ACTION, Collections.singletonList(filter), - params); + roleParams); actionContext.setTimeout(Short.valueOf(configuration.getDefaultAgentTaskTimeout(true))); + repoVersionHelper.addCommandRepository(actionContext, osFamily, repoVersionEnt, repoInfo); + String caption = String.format(INSTALL_PACKAGES_FULL_NAME + " on host %s", hostName); RequestStageContainer req = createRequest(caption); @@ -553,7 +503,7 @@ public class HostStackVersionResourceProvider extends AbstractControllerResource Stage stage; long stageId; ActionExecutionContext actionContext; - Map<String, String> commandParams = new HashMap(); + Map<String, String> commandParams = new HashMap<>(); commandParams.put("version", desiredRepoVersion); stage = stageFactory.createNew(req.getId(), http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java index fdb7c8d..14e0179 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java @@ -19,18 +19,33 @@ package org.apache.ambari.server.state.stack.upgrade; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.agent.CommandRepository; +import org.apache.ambari.server.agent.ExecutionCommand; +import org.apache.ambari.server.agent.ExecutionCommand.KeyNames; import org.apache.ambari.server.api.services.AmbariMetaInfo; +import org.apache.ambari.server.configuration.Configuration; +import org.apache.ambari.server.controller.ActionExecutionContext; +import org.apache.ambari.server.controller.ActionExecutionContext.ExecutionCommandVisitor; +import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.controller.internal.OperatingSystemResourceProvider; import org.apache.ambari.server.controller.internal.RepositoryResourceProvider; import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider; +import org.apache.ambari.server.controller.spi.SystemException; import org.apache.ambari.server.orm.entities.OperatingSystemEntity; import org.apache.ambari.server.orm.entities.RepositoryEntity; +import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; import org.apache.ambari.server.state.RepositoryInfo; +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.repository.VersionDefinitionXml; import org.apache.ambari.server.state.stack.UpgradePack; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -44,6 +59,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.inject.Inject; +import com.google.inject.Provider; import com.google.inject.Singleton; /** @@ -57,8 +73,11 @@ public class RepositoryVersionHelper { @Inject private Gson gson; - @Inject(optional = true) - private AmbariMetaInfo ambariMetaInfo; + @Inject + private Provider<AmbariMetaInfo> ami; + + @Inject + private Provider<Configuration> configuration; /** * Parses operating systems json to a list of entities. Expects json like: @@ -198,7 +217,7 @@ public class RepositoryVersionHelper { * @throws AmbariException if no upgrade packs suit the requirements */ public String getUpgradePackageName(String stackName, String stackVersion, String repositoryVersion, UpgradeType upgradeType) throws AmbariException { - final Map<String, UpgradePack> upgradePacks = ambariMetaInfo.getUpgradePacks(stackName, stackVersion); + final Map<String, UpgradePack> upgradePacks = ami.get().getUpgradePacks(stackName, stackVersion); for (UpgradePack upgradePack : upgradePacks.values()) { final String upgradePackName = upgradePack.getName(); @@ -218,4 +237,109 @@ public class RepositoryVersionHelper { throw new AmbariException("There were no suitable upgrade packs for stack " + stackName + " " + stackVersion + ((null != upgradeType) ? " and upgrade type " + upgradeType : "")); } + + /** + * Build the role parameters for an install command. + * + * @param amc the management controller. Tests don't use the same instance that gets injected. + * @param repoVersion the repository version + * @param osFamily the os family + * @param services the set of services to check for packages + * @param repos the list of individual repositories + * @return a Map<String, String> to use in + * @throws SystemException + */ + public Map<String, String> buildRoleParams(AmbariManagementController amc, RepositoryVersionEntity repoVersion, String osFamily, Set<String> servicesOnHost) + throws SystemException { + + StackId stackId = repoVersion.getStackId(); + + List<ServiceOsSpecific.Package> packages = new ArrayList<>(); + + for (String serviceName : servicesOnHost) { + ServiceInfo info; + + try { + if (ami.get().isServiceRemovedInStack(stackId.getStackName(), stackId.getStackVersion(), serviceName)) { + LOG.info(String.format("%s has been removed from stack %s-%s. Skip calculating its installation packages", stackId.getStackName(), stackId.getStackVersion(), serviceName)); + continue; //No need to calculate install packages for removed services + } + + info = ami.get().getService(stackId.getStackName(), stackId.getStackVersion(), serviceName); + } catch (AmbariException e) { + throw new SystemException(String.format("Cannot obtain stack information for %s-%s", stackId.getStackName(), stackId.getStackVersion()), e); + } + + List<ServiceOsSpecific.Package> packagesForService = amc.getPackagesForServiceHost(info, + new HashMap<String, String>(), osFamily); + + List<String> blacklistedPackagePrefixes = configuration.get().getRollingUpgradeSkipPackagesPrefixes(); + + for (ServiceOsSpecific.Package aPackage : packagesForService) { + if (!aPackage.getSkipUpgrade()) { + boolean blacklisted = false; + for (String prefix : blacklistedPackagePrefixes) { + if (aPackage.getName().startsWith(prefix)) { + blacklisted = true; + break; + } + } + if (! blacklisted) { + packages.add(aPackage); + } + } + } + } + + Map<String, String> roleParams = new HashMap<>(); + roleParams.put("stack_id", stackId.getStackId()); + roleParams.put("repository_version", repoVersion.getVersion()); + // !!! TODO make roleParams <String, Object> so we don't have to do this awfulness. + roleParams.put(KeyNames.PACKAGE_LIST, gson.toJson(packages)); + roleParams.put(KeyNames.REPO_VERSION_ID, repoVersion.getId().toString()); + + VersionDefinitionXml xml = null; + try { + xml = repoVersion.getRepositoryXml(); + } catch (Exception e) { + throw new SystemException(String.format("Could not load xml from repo version %s", + repoVersion.getVersion())); + } + + if (null != xml && StringUtils.isNotBlank(xml.getPackageVersion(osFamily))) { + roleParams.put(KeyNames.PACKAGE_VERSION, xml.getPackageVersion(osFamily)); + } + + return roleParams; + } + + /** + * Adds a command repository to the action context + * @param context the context + * @param osFamily the OS family + * @param repoVersion the repository version entity + * @param repos the repository entities + */ + public void addCommandRepository(ActionExecutionContext context, String osFamily, + RepositoryVersionEntity repoVersion, List<RepositoryEntity> repos) { + StackId stackId = repoVersion.getStackId(); + + final CommandRepository commandRepo = new CommandRepository(); + commandRepo.setRepositories(osFamily, repos); + commandRepo.setRepositoryVersion(repoVersion.getVersion()); + commandRepo.setRepositoryVersionId(repoVersion.getId()); + commandRepo.setStackName(stackId.getStackName()); + commandRepo.setUniqueSuffix(String.format("-repo-%s", repoVersion.getId())); + + context.addVisitor(new ExecutionCommandVisitor() { + @Override + public void visit(ExecutionCommand command) { + if (null == command.getRepositoryFile()) { + command.setRepositoryFile(commandRepo); + } + } + }); + } + + } http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/resources/custom_actions/scripts/install_packages.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/custom_actions/scripts/install_packages.py b/ambari-server/src/main/resources/custom_actions/scripts/install_packages.py index 33adce1..c12dff1 100644 --- a/ambari-server/src/main/resources/custom_actions/scripts/install_packages.py +++ b/ambari-server/src/main/resources/custom_actions/scripts/install_packages.py @@ -16,36 +16,30 @@ 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. -Ambari Agent - """ -import os import signal import re -import os.path -import ambari_simplejson as json # simplejson is much faster comparing to Python 2.6 json module and has the same functions set. +import ambari_simplejson as json -from resource_management import * -import resource_management -from resource_management.libraries.functions.list_ambari_managed_repos import list_ambari_managed_repos -from ambari_commons.os_check import OSCheck, OSConst +from ambari_commons.os_check import OSCheck from ambari_commons.str_utils import cbool, cint +from resource_management.core.exceptions import Fail +from resource_management.core.logger import Logger +from resource_management.core.resources import Package from resource_management.libraries.functions.packages_analyzer import allInstalledPackages, verifyDependencies from resource_management.libraries.functions import conf_select from resource_management.libraries.functions import stack_tools from resource_management.libraries.functions.stack_select import get_stack_versions from resource_management.libraries.functions.version import format_stack_version from resource_management.libraries.functions.repo_version_history \ - import read_actual_version_from_history_file, write_actual_version_to_history_file, REPO_VERSION_HISTORY_FILE -from resource_management.libraries.script.script import Script -from resource_management.core.resources.system import Execute -from resource_management.libraries.functions.stack_features import check_stack_feature + import read_actual_version_from_history_file, write_actual_version_to_history_file, REPO_VERSION_HISTORY_FILE from resource_management.libraries.functions import StackFeature - -from resource_management.core.logger import Logger - +from resource_management.libraries.functions.repository_util import create_repo_files, CommandRepository +from resource_management.libraries.functions.stack_features import check_stack_feature +from resource_management.libraries.resources.repository import Repository +from resource_management.libraries.script.script import Script class InstallPackages(Script): """ @@ -73,22 +67,20 @@ class InstallPackages(Script): self.repository_version_id = None + base_urls = [] # Select dict that contains parameters try: + if 'base_urls' in config['roleParams']: + base_urls = json.loads(config['roleParams']['base_urls']) + self.repository_version = config['roleParams']['repository_version'] - base_urls = json.loads(config['roleParams']['base_urls']) package_list = json.loads(config['roleParams']['package_list']) stack_id = config['roleParams']['stack_id'] + if 'repository_version_id' in config['roleParams']: self.repository_version_id = config['roleParams']['repository_version_id'] except KeyError: - # Last try - self.repository_version = config['commandParams']['repository_version'] - base_urls = json.loads(config['commandParams']['base_urls']) - package_list = json.loads(config['commandParams']['package_list']) - stack_id = config['commandParams']['stack_id'] - if 'repository_version_id' in config['commandParams']: - self.repository_version_id = config['commandParams']['repository_version_id'] + pass # current stack information self.current_stack_version_formatted = None @@ -110,9 +102,7 @@ class InstallPackages(Script): self.repository_version = self.repository_version.strip() - # Install/update repositories - installed_repositories = [] self.current_repositories = [] self.current_repo_files = set() @@ -130,21 +120,22 @@ class InstallPackages(Script): Logger.warning("Repository list is empty. Ambari may not be managing the repositories for {0}.".format(self.repository_version)) try: - append_to_file = False - for url_info in base_urls: - repo_name, repo_file = self.install_repository(url_info, append_to_file, template) - self.current_repositories.append(repo_name) - self.current_repo_files.add(repo_file) - append_to_file = True - - installed_repositories = list_ambari_managed_repos(self.stack_name) + if 'repositoryFile' in config: + create_repo_files(template, CommandRepository(config['repositoryFile'])) + else: + append_to_file = False + for url_info in base_urls: + repo_name, repo_file = self.install_repository(url_info, append_to_file, template) + self.current_repositories.append(repo_name) + self.current_repo_files.add(repo_file) + append_to_file = True + except Exception, err: - Logger.logger.exception("Cannot distribute repositories. Error: {0}".format(str(err))) + Logger.logger.exception("Cannot install repository files. Error: {0}".format(str(err))) num_errors += 1 # Build structured output with initial values self.structured_output = { - 'ambari_repositories': installed_repositories, 'installed_repository_version': self.repository_version, 'stack_id': stack_id, 'package_installation_result': 'FAIL' http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/params.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/params.py b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/params.py index 6193c11..50c5a40 100644 --- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/params.py +++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/params.py @@ -111,3 +111,5 @@ if has_hbase_masters: #repo params repo_info = config['hostLevelParams']['repo_info'] service_repo_info = default("/hostLevelParams/service_repo_info",None) + +repo_file = default("/repositoryFile", None) http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/repo_initialization.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/repo_initialization.py b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/repo_initialization.py index a35dce7..cbbc466 100644 --- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/repo_initialization.py +++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/repo_initialization.py @@ -19,11 +19,10 @@ limitations under the License. from ambari_commons.os_check import OSCheck from resource_management.libraries.resources.repository import Repository +from resource_management.libraries.functions.repository_util import create_repo_files, CommandRepository, UBUNTU_REPO_COMPONENTS_POSTFIX from resource_management.core.logger import Logger -import ambari_simplejson as json # simplejson is much faster comparing to Python 2.6 json module and has the same functions set. +import ambari_simplejson as json -# components_lits = repoName + postfix -_UBUNTU_REPO_COMPONENTS_POSTFIX = ["main"] def _alter_repo(action, repo_string, repo_template): """ @@ -45,17 +44,17 @@ def _alter_repo(action, repo_string, repo_template): repo['baseUrl'] = None if not 'mirrorsList' in repo: repo['mirrorsList'] = None - - ubuntu_components = [ repo['repoName'] ] + _UBUNTU_REPO_COMPONENTS_POSTFIX - + + ubuntu_components = [ repo['repoName'] ] + UBUNTU_REPO_COMPONENTS_POSTFIX + Repository(repo['repoId'], action = action, base_url = repo['baseUrl'], mirror_list = repo['mirrorsList'], repo_file_name = repo['repoName'], repo_template = repo_template, - components = ubuntu_components, # ubuntu specific - ) + components = ubuntu_components) # ubuntu specific + def install_repos(): import params @@ -63,6 +62,13 @@ def install_repos(): return template = params.repo_rhel_suse if OSCheck.is_suse_family() or OSCheck.is_redhat_family() else params.repo_ubuntu + + # use this newer way of specifying repositories, if available + if params.repo_file is not None: + create_repo_files(template, CommandRepository(params.repo_file)) + return + _alter_repo("create", params.repo_info, template) + if params.service_repo_info: _alter_repo("create", params.service_repo_info, template) http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/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 8f7b31d..6245708 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 @@ -219,9 +219,14 @@ public class ClusterStackVersionResourceProviderTest { Map<String, String> hostLevelParams = new HashMap<>(); StackId stackId = new StackId("HDP", "2.0.1"); + StackEntity stackEntity = new StackEntity(); + stackEntity.setStackName("HDP"); + stackEntity.setStackVersion("2.1.1"); + RepositoryVersionEntity repoVersion = new RepositoryVersionEntity(); repoVersion.setId(1l); repoVersion.setOperatingSystems(OS_JSON); + repoVersion.setStack(stackEntity); final String hostWithoutVersionableComponents = "host2"; @@ -647,12 +652,17 @@ public class ClusterStackVersionResourceProviderTest { File f = new File("src/test/resources/hbase_version_test.xml"); + StackEntity stackEntity = new StackEntity(); + stackEntity.setStackName("HDP"); + stackEntity.setStackVersion("2.1.1"); + RepositoryVersionEntity repoVersion = new RepositoryVersionEntity(); repoVersion.setId(1l); repoVersion.setOperatingSystems(OS_JSON); repoVersion.setVersionXml(IOUtils.toString(new FileInputStream(f))); repoVersion.setVersionXsd("version_definition.xsd"); repoVersion.setType(RepositoryType.STANDARD); + repoVersion.setStack(stackEntity); ambariMetaInfo.getComponent("HDP", "2.1.1", "HBASE", "HBASE_MASTER").setVersionAdvertised(true); @@ -890,12 +900,17 @@ public class ClusterStackVersionResourceProviderTest { File f = new File("src/test/resources/hbase_version_test.xml"); + StackEntity stackEntity = new StackEntity(); + stackEntity.setStackName("HDP"); + stackEntity.setStackVersion("2.1.1"); + RepositoryVersionEntity repoVersion = new RepositoryVersionEntity(); repoVersion.setId(1l); repoVersion.setOperatingSystems(os_json); repoVersion.setVersionXml(IOUtils.toString(new FileInputStream(f))); repoVersion.setVersionXsd("version_definition.xsd"); repoVersion.setType(RepositoryType.STANDARD); + repoVersion.setStack(stackEntity); ambariMetaInfo.getComponent("HDP", "2.1.1", "HBASE", "HBASE_MASTER").setVersionAdvertised(true); @@ -1096,8 +1111,8 @@ public class ClusterStackVersionResourceProviderTest { Assert.assertEquals(Float.valueOf(0.85f), successFactor); Assert.assertTrue(executionCommand.getRoleParams().containsKey(KeyNames.PACKAGE_VERSION)); - Assert.assertTrue(executionCommand.getRoleParams().containsKey("base_urls")); - Assert.assertEquals("[]", executionCommand.getRoleParams().get("base_urls")); + Assert.assertNotNull(executionCommand.getRepositoryFile()); + Assert.assertEquals(0, executionCommand.getRepositoryFile().getRepositories().size()); } @Test http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProviderTest.java index 4bed482..1ae83d4 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProviderTest.java @@ -154,9 +154,10 @@ public class HostStackVersionResourceProviderTest { StackEntity stack = new StackEntity(); stack.setStackName("HDP"); - stack.setStackVersion("2.2"); + stack.setStackVersion("2.0.1"); repoVersion.setStack(stack); repoVersion.setVersion("2.2"); + repoVersion.setId(1L); } @After http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java index c6ee875..5513271 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java @@ -40,6 +40,7 @@ import org.apache.ambari.server.actionmanager.HostRoleCommand; import org.apache.ambari.server.actionmanager.HostRoleCommandFactory; import org.apache.ambari.server.actionmanager.HostRoleStatus; import org.apache.ambari.server.agent.CommandReport; +import org.apache.ambari.server.agent.CommandRepository; import org.apache.ambari.server.agent.ExecutionCommand; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.controller.AmbariCustomCommandExecutionHelper; @@ -632,9 +633,6 @@ public class UpgradeActionTest { CommandReport report = finalizeUpgradeAction.execute(null); assertNotNull(report); assertEquals(HostRoleStatus.COMPLETED.name(), report.getStatus()); - - // Verify the metainfo url - verifyBaseRepoURL(helper, cluster, host, "http://foo1"); } /** @@ -699,6 +697,7 @@ public class UpgradeActionTest { } private void verifyBaseRepoURL(AmbariCustomCommandExecutionHelper helper, Cluster cluster, Host host, String expectedRepoBaseURL) throws AmbariException { + String repoInfo = helper.getRepoInfo(cluster, host); Gson gson = new Gson(); JsonElement element = gson.fromJson(repoInfo, JsonElement.class); @@ -709,6 +708,13 @@ public class UpgradeActionTest { JsonObject o = list.get(0).getAsJsonObject(); assertTrue(o.has("baseUrl")); assertEquals(expectedRepoBaseURL, o.get("baseUrl").getAsString()); + + CommandRepository commandRepo = helper.getCommandRepository(cluster, host); + + assertNotNull(commandRepo); + assertNotNull(commandRepo.getRepositories()); + assertEquals(1, commandRepo.getRepositories().size()); + assertEquals(expectedRepoBaseURL, commandRepo.getRepositories().iterator().next().getBaseUrl()); } @Test @@ -1019,9 +1025,6 @@ public class UpgradeActionTest { assertNotNull(report); assertEquals(HostRoleStatus.COMPLETED.name(), report.getStatus()); - // Verify the metainfo url - verifyBaseRepoURL(helper, cluster, host, "http://foo1"); - // ensure that history now exists historyEntites = serviceComponentDesiredStateDAO.findHistory(cluster.getClusterId(), nnSCH.getServiceName(), nnSCH.getServiceComponentName()); http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/test/java/org/apache/ambari/server/stack/UpdateActiveRepoVersionOnStartupTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/UpdateActiveRepoVersionOnStartupTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/UpdateActiveRepoVersionOnStartupTest.java index df69f68..d67cdfc 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/stack/UpdateActiveRepoVersionOnStartupTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/UpdateActiveRepoVersionOnStartupTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.IOException; +import java.lang.reflect.Field; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.orm.InMemoryDefaultTestModule; @@ -45,6 +46,7 @@ import org.junit.Test; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; import com.google.common.io.Resources; +import com.google.gson.Gson; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Provider; @@ -97,8 +99,14 @@ public class UpdateActiveRepoVersionOnStartupTest { ClusterDAO clusterDao = mock(ClusterDAO.class); ClusterVersionDAO clusterVersionDAO = mock(ClusterVersionDAO.class); repositoryVersionDao = mock(RepositoryVersionDAO.class); + final RepositoryVersionHelper repositoryVersionHelper = new RepositoryVersionHelper(); - AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class); + Field field = RepositoryVersionHelper.class.getDeclaredField("gson"); + field.setAccessible(true); + field.set(repositoryVersionHelper, new Gson()); + + + final AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class); StackManager stackManager = mock(StackManager.class); when(metaInfo.getStackManager()).thenReturn(stackManager); @@ -123,15 +131,26 @@ public class UpdateActiveRepoVersionOnStartupTest { stackInfo.getRepositories().add(repositoryInfo); when(stackManager.getStack("HDP", "2.3")).thenReturn(stackInfo); - Provider<RepositoryVersionHelper> repositoryVersionHelperProvider = mock(Provider.class); + final Provider<RepositoryVersionHelper> repositoryVersionHelperProvider = mock(Provider.class); when(repositoryVersionHelperProvider.get()).thenReturn(repositoryVersionHelper); + + + InMemoryDefaultTestModule testModule = new InMemoryDefaultTestModule() { @Override protected void configure() { - bind(RepositoryVersionHelper.class).toInstance(repositoryVersionHelper); + bind(RepositoryVersionHelper.class).toProvider(repositoryVersionHelperProvider); + bind(AmbariMetaInfo.class).toProvider(new Provider<AmbariMetaInfo>() { + @Override + public AmbariMetaInfo get() { + return metaInfo; + } + }); + requestStaticInjection(RepositoryVersionEntity.class); } }; + Injector injector = Guice.createInjector(testModule); if (addClusterVersion) { repoVersion = new RepositoryVersionEntity(); http://git-wip-us.apache.org/repos/asf/ambari/blob/b6866249/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelperTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelperTest.java index 3a5532b..339786e 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelperTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelperTest.java @@ -17,19 +17,15 @@ */ package org.apache.ambari.server.state.stack.upgrade; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import org.apache.ambari.server.state.RepositoryInfo; -import org.junit.Before; +import org.junit.Assert; import org.junit.Test; import com.google.gson.Gson; -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Injector; - -import junit.framework.Assert; /** * Tests the {@link RepositoryVersionHelper} class @@ -38,20 +34,15 @@ public class RepositoryVersionHelperTest { private RepositoryVersionHelper helper; - @Before - public void before() throws Exception { - final Injector injector = Guice.createInjector(new AbstractModule() { - - @Override - protected void configure() { - bind(Gson.class).toInstance(new Gson()); - } - }); - helper = injector.getInstance(RepositoryVersionHelper.class); - } - @Test public void testSerializeOperatingSystems() throws Exception { + Gson gson = new Gson(); + Field field = RepositoryVersionHelper.class.getDeclaredField("gson"); + field.setAccessible(true); + + RepositoryVersionHelper helper = new RepositoryVersionHelper(); + field.set(helper, gson); + final List<RepositoryInfo> repositories = new ArrayList<>(); final RepositoryInfo repository = new RepositoryInfo(); repository.setBaseUrl("baseurl");