AMBARI-9964. Rolling Upgrade: Expose FinalizeUpgradeAction to API or force transition from UPGRADED to CURRENT for cluster_version via API request (dlysnichenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/8775d884 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/8775d884 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/8775d884 Branch: refs/heads/trunk Commit: 8775d8846da2ecaf82a16a92712d47d8bc5f5745 Parents: 4894eab Author: Lisnichenko Dmitro <dlysniche...@hortonworks.com> Authored: Fri Mar 6 20:53:27 2015 +0200 Committer: Lisnichenko Dmitro <dlysniche...@hortonworks.com> Committed: Fri Mar 6 20:55:39 2015 +0200 ---------------------------------------------------------------------- .../services/ClusterStackVersionService.java | 17 +++ .../ClusterStackVersionResourceProvider.java | 102 ++++++++++++++- .../upgrades/FinalizeUpgradeAction.java | 10 +- ambari-server/src/main/python/upgradeHelper.py | 47 +++++-- ...ClusterStackVersionResourceProviderTest.java | 123 ++++++++++++++++++- .../src/test/python/TestUpgradeHelper.py | 53 ++++++++ 6 files changed, 336 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/8775d884/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterStackVersionService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterStackVersionService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterStackVersionService.java index eb8a461..8fe1499 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterStackVersionService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterStackVersionService.java @@ -22,6 +22,7 @@ import java.util.Map; import javax.ws.rs.GET; import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -120,6 +121,22 @@ public class ClusterStackVersionService extends BaseService { return handleRequest(headers, body, ui, Request.Type.POST, createResource(null)); } + + /** + * Handles: POST /{clustername}/stack_versions requests + * triggering Finalize during manual Rolling Upgrade + * + * @param body http body + * @param headers http headers + * @param ui uri info + * @return information regarding the created services + */ + @PUT + @Produces("text/plain") + public Response updateRequests(String body, @Context HttpHeaders headers, @Context UriInfo ui) { + return handleRequest(headers, body, ui, Request.Type.PUT, createResource(null)); + } + /** * Create a cluster stack version resource instance. * http://git-wip-us.apache.org/repos/asf/ambari/blob/8775d884/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 0cf89a3..e93e653 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 @@ -27,13 +27,21 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import com.google.inject.Injector; import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.Role; import org.apache.ambari.server.StaticallyInject; import org.apache.ambari.server.actionmanager.ActionManager; +import org.apache.ambari.server.actionmanager.HostRoleCommand; +import org.apache.ambari.server.actionmanager.HostRoleStatus; 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.CommandReport; +import org.apache.ambari.server.agent.ExecutionCommand; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.controller.ActionExecutionContext; @@ -58,6 +66,7 @@ import org.apache.ambari.server.orm.entities.HostVersionEntity; 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.serveraction.upgrades.FinalizeUpgradeAction; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Host; import org.apache.ambari.server.state.RepositoryVersionState; @@ -109,7 +118,6 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou add(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID); add(CLUSTER_STACK_VERSION_STACK_PROPERTY_ID); add(CLUSTER_STACK_VERSION_VERSION_PROPERTY_ID); - add(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID); add(CLUSTER_STACK_VERSION_HOST_STATES_PROPERTY_ID); add(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID); add(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID); @@ -150,6 +158,16 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou @Inject private static Configuration configuration; + @Inject + private static Injector injector; + + /** + * We have to include such a hack here, because if we + * make finalizeUpgradeAction field static and request injection + * for it, there will be a circle dependency error + */ + private FinalizeUpgradeAction finalizeUpgradeAction = injector.getInstance(FinalizeUpgradeAction.class); + /** * Constructor. */ @@ -410,12 +428,90 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou return requestStages; } - + /** + * The only appliance of this method is triggering Finalize during + * manual Rolling Upgrade + */ @Override public RequestStatus updateResources(Request request, Predicate predicate) throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { - throw new SystemException("Method not supported"); + try { + Iterator<Map<String, Object>> iterator = request.getProperties().iterator(); + String clName; + final String desiredRepoVersion; + if (request.getProperties().size() != 1) { + throw new UnsupportedOperationException("Multiple requests cannot be executed at the same time."); + } + Map<String, Object> propertyMap = iterator.next(); + + Set<String> requiredProperties = new HashSet<String>() {{ + add(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID); + add(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID); + add(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID); + }}; + + for (String requiredProperty : requiredProperties) { + if (!propertyMap.containsKey(requiredProperty)) { + throw new IllegalArgumentException( + String.format("The required property %s is not defined", + requiredProperty)); + } + } + + clName = (String) propertyMap.get(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID); + String desiredDisplayRepoVersion = (String) propertyMap.get(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID); + RepositoryVersionEntity rve = repositoryVersionDAO.findByDisplayName(desiredDisplayRepoVersion); + if (rve == null) { + throw new IllegalArgumentException( + String.format("Repository version with display name %s does not exist", + desiredDisplayRepoVersion)); + } + desiredRepoVersion = rve.getVersion(); + String newStateStr = (String) propertyMap.get(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID); + + LOG.info("Initiating finalization for manual upgrade to version {} for cluster {}", + desiredRepoVersion, clName); + + Map<String, String> args = new HashMap<String, String>(); + if (newStateStr.equals(RepositoryVersionState.CURRENT.toString())) { + // Finalize upgrade workflow + args.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade"); + } else if (newStateStr.equals(RepositoryVersionState.INSTALLED.toString())) { + // Finalize downgrade workflow + args.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "downgrade"); + } else { + throw new IllegalArgumentException( + String.format("Invalid desired state %s. Should be either CURRENT or INSTALLED", + newStateStr)); + } + args.put(FinalizeUpgradeAction.VERSION_KEY, desiredRepoVersion); + args.put(FinalizeUpgradeAction.CLUSTER_NAME_KEY, clName); + + ExecutionCommand command = new ExecutionCommand(); + command.setCommandParams(args); + command.setClusterName(clName); + finalizeUpgradeAction.setExecutionCommand(command); + HostRoleCommand hostRoleCommand = new HostRoleCommand("none", + Role.AMBARI_SERVER_ACTION, null, null); + finalizeUpgradeAction.setHostRoleCommand(hostRoleCommand); + + CommandReport report = finalizeUpgradeAction.execute(null); + + LOG.info("Finalize output:"); + LOG.info("STDERR: {}", report.getStdErr()); + LOG.info("STDOUT: {}", report.getStdOut()); + + if (report.getStatus().equals(HostRoleStatus.COMPLETED.toString())) { + return getRequestStatus(null); + } else { + throw new SystemException("Finalization failed"); + } + } catch (AmbariException e) { + throw new SystemException("Can not perform request", e); + } catch (InterruptedException e) { + throw new SystemException("Can not perform request", e); + } } @Override http://git-wip-us.apache.org/repos/asf/ambari/blob/8775d884/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java index d8e5e92..01bd9c7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java @@ -54,6 +54,9 @@ import com.google.inject.Inject; */ public class FinalizeUpgradeAction extends AbstractServerAction { + public static final String CLUSTER_NAME_KEY = "cluster_name"; + public static final String UPGRADE_DIRECTION_KEY = "upgrade_direction"; + public static final String VERSION_KEY = "version"; /** * The Cluster that this ServerAction implementation is executing on @@ -79,10 +82,11 @@ public class FinalizeUpgradeAction extends AbstractServerAction { Map<String, String> commandParams = getExecutionCommand().getCommandParams(); - boolean isDowngrade = commandParams.containsKey("upgrade_direction") && - "downgrade".equals(commandParams.get("upgrade_direction").toLowerCase()); + boolean isDowngrade = commandParams.containsKey(UPGRADE_DIRECTION_KEY) && + "downgrade".equals(commandParams.get(UPGRADE_DIRECTION_KEY).toLowerCase()); + + String version = commandParams.get(VERSION_KEY); - String version = commandParams.get("version"); String clusterName = getExecutionCommand().getClusterName(); if (isDowngrade) { http://git-wip-us.apache.org/repos/asf/ambari/blob/8775d884/ambari-server/src/main/python/upgradeHelper.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/python/upgradeHelper.py b/ambari-server/src/main/python/upgradeHelper.py index 11292e9..2426d69 100644 --- a/ambari-server/src/main/python/upgradeHelper.py +++ b/ambari-server/src/main/python/upgradeHelper.py @@ -165,6 +165,7 @@ class Options(Const): MODIFY_CONFIG_ACTION = "update-configs" BACKUP_CONFIG_ACTION = "backup-configs" INSTALL_YARN_MR2_ACTION = "install-yarn-mr2" + FINALIZE_RU_ACTION = "finalize-ru" MR_MAPPING_FILE = "mr_mapping" CAPACITY_SCHEDULER_TAG = "capacity-scheduler" @@ -196,6 +197,9 @@ class Options(Const): # for verify action REPORT_FILE = None + # for finalize action + REPO_VERSION = None + API_TOKENS = { "user": None, "pass": None @@ -897,7 +901,9 @@ def install_services(): "the status of the install requests." -def validate_response(response, expect_body): +def validate_response(response, expect_body, http_code): + if http_code is not None and http_code < 200 or http_code >= 300: + return 1, "HTTP code {0}\n".format(http_code) + response if expect_body: if "\"href\" : \"" not in response: return 1, response @@ -910,16 +916,13 @@ def validate_response(response, expect_body): def curl(url, tokens=None, headers=None, request_type="GET", data=None, parse=False, - simulate=None, validate=False, validate_expect_body=False): + simulate=None, validate=False, validate_expect_body=False, request_http_code=False): simulate_only = Options.CURL_PRINT_ONLY is not None or (simulate is not None and simulate is True) print_url = Options.CURL_PRINT_ONLY is not None and simulate is not None curl_path = '/usr/bin/curl' - curl_list = [curl_path] - - curl_list.append('-X') - curl_list.append(request_type) + curl_list = [curl_path, '-X', request_type] if tokens is not None: curl_list.append('-u') @@ -928,6 +931,9 @@ def curl(url, tokens=None, headers=None, request_type="GET", data=None, parse=Fa curl_list.append('-u') curl_list.append("%s:%s" % (Options.API_TOKENS["user"], Options.API_TOKENS["pass"])) + if request_http_code: + curl_list += ['-w', '\n%{http_code}'] + if request_type in Options.POST_REQUESTS: curl_list.append(url) @@ -949,12 +955,17 @@ def curl(url, tokens=None, headers=None, request_type="GET", data=None, parse=Fa if print_url: Options.logger.info(" ".join(curl_list)) + http_code = None if not simulate_only: osStat = subprocess.Popen( curl_list, stderr=subprocess.PIPE, stdout=subprocess.PIPE) out, err = osStat.communicate() + if request_http_code: + out_lines = out.splitlines() + http_code = int(out_lines[-1]) + out = '\n'.join(out_lines[0:-1]) if 0 != osStat.returncode: error = "curl call failed. out: " + out + " err: " + err Options.logger.error(error) @@ -965,7 +976,7 @@ def curl(url, tokens=None, headers=None, request_type="GET", data=None, parse=Fa out = "{}" if validate and not simulate_only: - retcode, errdata = validate_response(out, validate_expect_body) + retcode, errdata = validate_response(out, validate_expect_body, http_code) if not retcode == 0: raise FatalException(retcode, errdata) @@ -1134,6 +1145,18 @@ def verify_configuration(): Options.logger.error("Report file close error: %s" % e.message) +def finalize_ru(): + TARGET_URL = Options.CLUSTER_URL + '/stack_versions' + request = { + "ClusterStackVersions": { + "repository_version": Options.REPO_VERSION, + "state": "CURRENT" + } + } + curl(TARGET_URL, request_type="PUT", data=request, + validate=True, validate_expect_body=False, request_http_code=True) + + def report_formatter(report_file, config_item, analyzed_list_item): prefix = "Configuration item %s" % config_item if analyzed_list_item["fail"]["count"] > 0: @@ -1155,7 +1178,8 @@ def main(): Options.MODIFY_CONFIG_ACTION: modify_configs, Options.INSTALL_YARN_MR2_ACTION: install_services, Options.BACKUP_CONFIG_ACTION: backup_configs, - Options.VERIFY_ACTION: verify_configuration + Options.VERIFY_ACTION: verify_configuration, + Options.FINALIZE_RU_ACTION: finalize_ru } parser = optparse.OptionParser(usage="usage: %prog [options] action\n Valid actions: " @@ -1179,6 +1203,8 @@ def main(): parser.add_option('--password', default=None, help="Ambari admin password", dest="password") parser.add_option('--clustername', default=None, help="Cluster name", dest="clustername") + parser.add_option('--repository-version', default=None, help="Repository version", dest="repo_version") + (options, args) = parser.parse_args() Options.initialize_logger(options.logfile) options.warnings = [] @@ -1211,6 +1237,10 @@ def main(): if options.report is None: options.warnings.append("Should be provided report option") + if action == Options.FINALIZE_RU_ACTION: + if options.repo_version is None: + options.warnings.append("Should be provided repository-version option") + if len(options.warnings) != 0: print parser.print_help() for warning in options.warnings: @@ -1231,6 +1261,7 @@ def main(): "pass": options.password } Options.REPORT_FILE = options.report + Options.REPO_VERSION = options.repo_version if action in action_list: Options.initialize() http://git-wip-us.apache.org/repos/asf/ambari/blob/8775d884/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 e05405c..29677fc 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 @@ -27,6 +27,7 @@ import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.actionmanager.ActionManager; import org.apache.ambari.server.actionmanager.HostRoleCommand; import org.apache.ambari.server.agent.AgentEnv; +import org.apache.ambari.server.agent.CommandReport; import org.apache.ambari.server.agent.DiskInfo; import org.apache.ambari.server.agent.HostInfo; import org.apache.ambari.server.api.services.AmbariMetaInfo; @@ -45,6 +46,8 @@ import org.apache.ambari.server.orm.InMemoryDefaultTestModule; import org.apache.ambari.server.orm.dao.RepositoryVersionDAO; import org.apache.ambari.server.orm.entities.HostVersionEntity; import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; +import org.apache.ambari.server.serveraction.upgrades.FinalizeUpgradeAction; +import org.apache.ambari.server.stack.StackManager; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.state.ConfigHelper; @@ -59,9 +62,11 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import java.lang.reflect.Field; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -89,8 +94,6 @@ import static org.junit.Assert.fail; /** * ClusterStackVersionResourceProvider tests. */ -//@RunWith(PowerMockRunner.class) -@PrepareForTest(AmbariManagementControllerImpl.class) public class ClusterStackVersionResourceProviderTest { private Injector injector; @@ -121,6 +124,7 @@ public class ClusterStackVersionResourceProviderTest { // Create instances of mocks repositoryVersionDAOMock = createNiceMock(RepositoryVersionDAO.class); configHelper = createNiceMock(ConfigHelper.class); + // Initialize injector InMemoryDefaultTestModule module = new InMemoryDefaultTestModule(); injector = Guice.createInjector(Modules.override(module).with(new MockModule())); @@ -234,11 +238,126 @@ public class ClusterStackVersionResourceProviderTest { verify(managementController, response, clusters); } + + /** + * Tests manual finalization scenario + * @throws Exception + */ + @Test + public void testUpdateResources() throws Exception { + Resource.Type type = Resource.Type.ClusterStackVersion; + + AmbariManagementController managementController = createMock(AmbariManagementController.class); + Clusters clusters = createNiceMock(Clusters.class); + Cluster cluster = createNiceMock(Cluster.class); + StackId stackId = new StackId("HDP", "2.0.1"); + + final Host host1 = createNiceMock("host1", Host.class); + final Host host2 = createNiceMock("host2", Host.class); + expect(host1.getHostName()).andReturn("host1").anyTimes(); + expect(host1.getOsFamily()).andReturn("redhat6").anyTimes(); + expect(host2.getHostName()).andReturn("host2").anyTimes(); + expect(host2.getOsFamily()).andReturn("redhat6").anyTimes(); + replay(host1, host2); + Map<String, Host> hostsForCluster = new HashMap<String, Host>() {{ + put(host1.getHostName(), host1); + put(host2.getHostName(), host2); + }}; + + ServiceComponentHost sch = createMock(ServiceComponentHost.class); + List<ServiceComponentHost> schs = Collections.singletonList(sch); + + RepositoryVersionEntity repoVersion = new RepositoryVersionEntity(); + repoVersion.setOperatingSystems(operatingSystemsJson); + + ServiceOsSpecific.Package hivePackage = new ServiceOsSpecific.Package(); + hivePackage.setName("hive"); + List<ServiceOsSpecific.Package> packages = Collections.singletonList(hivePackage); + + ActionManager actionManager = createNiceMock(ActionManager.class); + + RequestStatusResponse response = createNiceMock(RequestStatusResponse.class); + ResourceProviderFactory resourceProviderFactory = createNiceMock(ResourceProviderFactory.class); + ResourceProvider csvResourceProvider = createNiceMock(ClusterStackVersionResourceProvider.class); + + CommandReport report = createNiceMock(CommandReport.class); + FinalizeUpgradeAction finalizeUpgradeAction = createNiceMock(FinalizeUpgradeAction.class); + + AbstractControllerResourceProvider.init(resourceProviderFactory); + + Map<String, Map<String, String>> hostConfigTags = new HashMap<String, Map<String, String>>(); + expect(configHelper.getEffectiveDesiredTags(anyObject(ClusterImpl.class), anyObject(String.class))).andReturn(hostConfigTags); + + expect(managementController.getClusters()).andReturn(clusters).anyTimes(); + expect(managementController.getAmbariMetaInfo()).andReturn(ambariMetaInfo).anyTimes(); + expect(managementController.getAuthName()).andReturn("admin").anyTimes(); + expect(managementController.getActionManager()).andReturn(actionManager).anyTimes(); + expect(managementController.getJdkResourceUrl()).andReturn("/JdkResourceUrl").anyTimes(); + expect(managementController.getPackagesForServiceHost(anyObject(ServiceInfo.class), + (Map<String, String>) anyObject(List.class), anyObject(String.class))).andReturn(packages).anyTimes(); + + expect(resourceProviderFactory.getHostResourceProvider(anyObject(Set.class), anyObject(Map.class), + eq(managementController))).andReturn(csvResourceProvider).anyTimes(); + + expect(clusters.getCluster(anyObject(String.class))).andReturn(cluster); + expect(clusters.getHostsForCluster(anyObject(String.class))).andReturn(hostsForCluster); + + expect(cluster.getCurrentStackVersion()).andReturn(stackId); + expect(cluster.getServiceComponentHosts(anyObject(String.class))).andReturn(schs).anyTimes(); + + expect(sch.getServiceName()).andReturn("HIVE").anyTimes(); + + expect(repositoryVersionDAOMock.findByDisplayName(anyObject(String.class))).andReturn(repoVersion); + + expect(actionManager.getRequestTasks(anyLong())).andReturn(Collections.<HostRoleCommand>emptyList()).anyTimes(); + + expect(finalizeUpgradeAction.execute(null)).andReturn(report); + + expect(report.getStdOut()).andReturn("Dummy stdout"); + expect(report.getStdErr()).andReturn("Dummy stderr"); + expect(report.getStatus()).andReturn("COMPLETED"); + + // replay + replay(managementController, response, clusters, resourceProviderFactory, csvResourceProvider, + cluster, repositoryVersionDAOMock, configHelper, sch, actionManager, finalizeUpgradeAction, report); + + ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider( + type, + PropertyHelper.getPropertyIds(type), + PropertyHelper.getKeyPropertyIds(type), + managementController); + + injector.injectMembers(provider); + + // Have to inject instance manually because injection via DI fails + Field field = ClusterStackVersionResourceProvider.class.getDeclaredField("finalizeUpgradeAction"); + field.setAccessible(true); + field.set((ClusterStackVersionResourceProvider)provider, finalizeUpgradeAction); + + // add the property map to a set for the request. add more maps for multiple creates + Map<String, Object> properties = new LinkedHashMap<String, Object>(); + + // add properties to the request map + properties.put(ClusterStackVersionResourceProvider.CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID, "Cluster100"); + properties.put(ClusterStackVersionResourceProvider.CLUSTER_STACK_VERSION_STATE_PROPERTY_ID, "CURRENT"); + properties.put(ClusterStackVersionResourceProvider.CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID, "HDP-2.2.2.0-2561"); + + // create the request + Request request = PropertyHelper.getUpdateRequest(properties, null); + + provider.updateResources(request, null); + + // verify + verify(managementController, response); + } + + public class MockModule extends AbstractModule { @Override protected void configure() { bind(RepositoryVersionDAO.class).toInstance(repositoryVersionDAOMock); bind(ConfigHelper.class).toInstance(configHelper); + //bind(FinalizeUpgradeAction.class).toInstance(finalizeUpgradeAction); } } } http://git-wip-us.apache.org/repos/asf/ambari/blob/8775d884/ambari-server/src/test/python/TestUpgradeHelper.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/python/TestUpgradeHelper.py b/ambari-server/src/test/python/TestUpgradeHelper.py index 2f47620..8e88883 100644 --- a/ambari-server/src/test/python/TestUpgradeHelper.py +++ b/ambari-server/src/test/python/TestUpgradeHelper.py @@ -78,6 +78,7 @@ class TestUpgradeHelper(TestCase): report = "report.txt" warnings = [] printonly = False + repo_version = None args = ["update-configs"] modify_action_mock.return_value = MagicMock() @@ -93,5 +94,57 @@ class TestUpgradeHelper(TestCase): self.assertEqual(options.clustername, upgradeHelper.Options.CLUSTER_NAME) + @patch("optparse.OptionParser") + @patch("upgradeHelper.finalize_ru") + @patch("__builtin__.open") + def test_Finalize_options(self, open_mock, finalize_ru_mock, option_parser_mock): + class options(object): + user = "test_user" + hostname = "127.0.0.1" + clustername = "test1" + password = "test_password" + upgrade_json = None + from_stack = None + to_stack = None + logfile = "test.log" + report = None + warnings = [] + printonly = False + repo_version = None + + args = ["finalize-ru"] + test_mock = MagicMock() + test_mock.parse_args = lambda: (options, args) + option_parser_mock.return_value = test_mock + + try: + upgradeHelper.main() + except upgradeHelper.FatalException: + # Expected + pass + + class options(object): + user = "test_user" + hostname = "127.0.0.1" + clustername = "test1" + password = "test_password" + upgrade_json = None + from_stack = None + to_stack = None + logfile = "test.log" + report = None + warnings = [] + printonly = False + repo_version = 'HDP-2.2.2.0-2561' + + args = ["finalize-ru"] + test_mock = MagicMock() + test_mock.parse_args = lambda: (options, args) + option_parser_mock.return_value = test_mock + + upgradeHelper.main() + self.assertTrue(finalize_ru_mock.called) + + if __name__ == "__main__": unittest.main()