class AwsUpscaleService {

    public List<CloudResourceStatus> upscale(AuthenticatedContext ac, CloudStack stack, List<CloudResource> resources) {
        AmazonCloudFormationRetryClient cloudFormationClient = getCloudFormationRetryClient(ac);
        AwsCredentialView credentialView = new AwsCredentialView(ac.getCloudCredential());
        String regionName = ac.getCloudContext().getLocation().getRegion().value();
        AmazonAutoScalingRetryClient amazonASClient = getAutoScalingRetryClient(ac);
        AmazonEC2Client amazonEC2Client = getEC2Client(ac);

        List<Group> scaledGroups = cloudResourceHelper.getScaledGroups(stack);
        Map<String, Group> desiredAutoscalingGroupsByName = getAutoScaleGroupsByNameFromCloudFormationTemplate(ac, cloudFormationClient, scaledGroups);
        LOGGER.info("Desired autoscaling groups: {}", desiredAutoscalingGroupsByName);
        awsAutoScalingService.resumeAutoScaling(amazonASClient, desiredAutoscalingGroupsByName.keySet(), UPSCALE_PROCESSES);
        Map<String, Integer> originalAutoScalingGroupsBySize = getAutoScalingGroupsBySize(desiredAutoscalingGroupsByName.keySet(), amazonASClient);
        LOGGER.info("Update autoscaling groups for stack: {}", ac.getCloudContext().getName());
        Date timeBeforeASUpdate = new Date();
        updateAutoscalingGroups(amazonASClient, desiredAutoscalingGroupsByName, originalAutoScalingGroupsBySize);
        try {
            awsAutoScalingService.scheduleStatusChecks(scaledGroups, ac, cloudFormationClient, timeBeforeASUpdate);
        } catch (AmazonAutoscalingFailed amazonAutoscalingFailed) {
            return recoverOriginalState(ac, stack, amazonASClient, desiredAutoscalingGroupsByName, originalAutoScalingGroupsBySize,
                    amazonAutoscalingFailed);
        }
        awsAutoScalingService.suspendAutoScaling(ac, stack);
        List<CloudResource> instances = cfStackUtil.getInstanceCloudResources(ac, cloudFormationClient, amazonASClient, scaledGroups);
        associateElasticIpWithNewInstances(stack, resources, cloudFormationClient, amazonEC2Client, scaledGroups, instances);

        List<Group> groupsWithNewInstances = getGroupsWithNewInstances(scaledGroups);
        List<CloudResource> newInstances = getNewInstances(scaledGroups, instances);
        List<CloudResource> reattachableVolumeSets = getReattachableVolumeSets(scaledGroups, resources);
        List<CloudResource> networkResources = resources.stream()
                .filter(cloudResource -> ResourceType.AWS_SUBNET.equals(cloudResource.getType()))
                .collect(Collectors.toList());
        awsComputeResourceService.buildComputeResourcesForUpscale(ac, stack, groupsWithNewInstances, newInstances, reattachableVolumeSets, networkResources);

        awsTaggingService.tagRootVolumes(ac, amazonEC2Client, instances, stack.getTags());

        awsCloudWatchService.addCloudWatchAlarmsForSystemFailures(instances, stack, regionName, credentialView);

        return singletonList(new CloudResourceStatus(cfStackUtil.getCloudFormationStackResource(resources), ResourceStatus.UPDATED));
    }

}