@Test public void testIncrementMinInstancesForAsgHappy() { String logicalId = "asg id"; String instanceId = "instance id"; int minSize = 2; when(autoScalingClient.describeAutoScalingGroups( new DescribeAutoScalingGroupsRequest().withAutoScalingGroupNames(logicalId)) ).thenReturn( new DescribeAutoScalingGroupsResult() .withAutoScalingGroups( new AutoScalingGroup().withInstances( new Instance().withInstanceId(instanceId)) .withMinSize(minSize) ) ); autoScalingService.updateMinInstancesForAutoScalingGroup(logicalId, minSize - 1); verify(autoScalingClient).updateAutoScalingGroup(new UpdateAutoScalingGroupRequest() .withAutoScalingGroupName(logicalId) .withMinSize(minSize - 1)); }
/** * Returns auto scaling groups that have the CLUSTER_TAG_KEY tag * @return collection of AutoScalingGroup that contain the CLUSTER_TAG_KEY */ private Collection<AutoScalingGroup> findAutoscalingGroups() { String token = null; List<AutoScalingGroup> groupList = new ArrayList<>(); do { DescribeAutoScalingGroupsRequest request = new DescribeAutoScalingGroupsRequest(); request.setNextToken(token); DescribeAutoScalingGroupsResult result = asgClient.describeAutoScalingGroups(request); result.getAutoScalingGroups().stream() .filter(a -> containsTag(a.getTags())) .forEach(groupList::add); token = result.getNextToken(); } while(!Strings.isNullOrEmpty(token)); return groupList; }
/** * For a given AutoScaling group logical id, get the public dns names associated with each instance. * * @param logicalId AutoScaling group logical id * @return List of public dns names */ public List<String> getPublicDnsForAutoScalingGroup(final String logicalId) { final List<String> instanceIds = Lists.newLinkedList(); final Optional<AutoScalingGroup> autoScalingGroup = describeAutoScalingGroup(logicalId); final List<String> publicDnsNames = Lists.newLinkedList(); if (autoScalingGroup.isPresent()) { autoScalingGroup.get() .getInstances().stream().forEach(instance -> instanceIds.add(instance.getInstanceId())); final DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest() .withInstanceIds(instanceIds); final DescribeInstancesResult describeInstancesResult = ec2Client.describeInstances(describeInstancesRequest); describeInstancesResult.getReservations().forEach(reservation -> reservation.getInstances().stream().forEach(instance -> publicDnsNames.add(instance.getPublicDnsName())) ); } return publicDnsNames; }
private Optional<AutoScalingGroup> describeAutoScalingGroup(final String autoscalingGroupName) { final DescribeAutoScalingGroupsRequest describeAsg = new DescribeAutoScalingGroupsRequest() .withAutoScalingGroupNames(autoscalingGroupName); final DescribeAutoScalingGroupsResult result = autoScalingClient.describeAutoScalingGroups(describeAsg); return result.getAutoScalingGroups().stream().findFirst(); }
/*** * Get list of {@link AutoScalingGroup}s for a given tag * * @param tag Tag to filter the auto scaling groups * @return List of {@link AutoScalingGroup}s qualifying the filter tag */ public List<AutoScalingGroup> getAutoScalingGroupsWithTag(Tag tag) { final AmazonAutoScaling autoScaling = getAmazonAutoScalingClient(); final DescribeAutoScalingGroupsRequest describeAutoScalingGroupsRequest = new DescribeAutoScalingGroupsRequest(); final List<AutoScalingGroup> allAutoScalingGroups = autoScaling .describeAutoScalingGroups(describeAutoScalingGroupsRequest) .getAutoScalingGroups(); final List<AutoScalingGroup> filteredAutoScalingGroups = Lists.newArrayList(); for (AutoScalingGroup autoScalingGroup : allAutoScalingGroups) { for (TagDescription tagDescription : autoScalingGroup.getTags()) { if (tagDescription.getKey().equalsIgnoreCase(tag.getKey()) && tagDescription.getValue().equalsIgnoreCase(tag.getValue())) { filteredAutoScalingGroups.add(autoScalingGroup); } } } return filteredAutoScalingGroups; }
private List<Instance> listGroupInstances(AutoScalingGroup autoScalingGroup) throws Exception { List<String> instanceIds = autoScalingGroup.getInstances().stream() .map(com.amazonaws.services.autoscaling.model.Instance::getInstanceId).collect(Collectors.toList()); if (instanceIds.isEmpty()) { // note: we don't want to call get instances with an emtpy list // since this causes DescribeInstances to get *all* instances in the // region (not just the ones in our Auto Scaling Group, which is // what we want) return new ArrayList<>(); } List<Filter> filters = Collections.emptyList(); Callable<List<Instance>> requester = new GetInstances(getAwsCredentials(), getRegion(), getClientConfig(), instanceIds, filters); int initialDelay = 1; int maxAttempts = 10; // max 2 ^ 9 - 1 seconds = 511 seconds String name = String.format("await-describe-instances"); Retryable<List<Instance>> retryer = Retryers.exponentialBackoffRetryer(name, requester, initialDelay, TimeUnit.SECONDS, maxAttempts, instancesPresent(instanceIds)); return retryer.call(); }
@Override public List<Machine> startMachines(int count) throws StartMachinesException { checkState(isConfigured(), "attempt to use unconfigured driver"); try { // We simply set the desired size of the scaling group without // waiting for the request to be fulfilled, simply because there is // no bulletproof method of knowing when this particular desired // size request has taken effect. Waiting for the group size to // reach the desired size is problematic, since the desired size may // be set to some other value while we are waiting. AutoScalingGroup group = this.client.getAutoScalingGroup(scalingGroupName()); LaunchConfiguration launchConfig = this.client.getLaunchConfiguration(group.getLaunchConfigurationName()); int newDesiredSize = group.getDesiredCapacity() + count; LOG.info("starting {} new instance(s) in scaling group '{}': " + "changing desired capacity from {} to {}", count, scalingGroupName(), group.getDesiredCapacity(), newDesiredSize); this.client.setDesiredSize(scalingGroupName(), newDesiredSize); return pseudoMachines(count, launchConfig); } catch (Exception e) { List<Machine> empty = Collections.emptyList(); throw new StartMachinesException(count, empty, e); } }
/** * Terminates a single machine from the Auto Scaling Group. * * @param machineId * * @throws NotFoundException * @throws AmazonClientException */ private void terminateMachine(String machineId) throws NotFoundException, AmazonClientException { checkState(isConfigured(), "attempt to use unconfigured driver"); if (machineId.startsWith(REQUESTED_ID_PREFIX)) { // we were asked to terminate a placeholder instance (a // requested, but not yet assigned, instance). just decrement // desiredCapacity of the group. AutoScalingGroup group = this.client.getAutoScalingGroup(scalingGroupName()); int desiredSize = group.getDesiredCapacity(); int newSize = desiredSize - 1; LOG.debug("termination request for placeholder instance {}, " + "reducing desiredCapacity from {} to {}", machineId, desiredSize, newSize); this.client.setDesiredSize(scalingGroupName(), newSize); } else { LOG.info("terminating instance {}", machineId); this.client.terminateInstance(scalingGroupName(), machineId); } }
/** * Exercises the scenario when a call to describe the autoscaling group * yields a different outcome from a call to list the group members, which * may happen since there is always a time-window between those calls where * things may change. We need to verify that this doesn't confuse the * AwsAsDriver when it creates pseudo-instances in REQUESTED state. * <p/> * In this particular case, the scenario is that a call is made to describe * the autoscaling group (desiredCapacity: 1, instances: 0), then the * requested instance comes online and the call to get the group members * returns 1 RUNNING instance. In this case, the pool driver should act as * if the first call to describe the group returned (desiredCapacity: 1, * instances: 1) and not return any pseudo-machines in state REQUESTED. */ @Test public void listMachinesOnInconsistentApiInformation() { int desiredCapacity = 1; List<Instance> emptyGroup = ec2Instances(); // empty group returned on call to describe autoscaling group AutoScalingGroup groupAtT1 = group(GROUP_NAME, ONDEMAND_LAUNCH_CONFIG, desiredCapacity, emptyGroup); when(this.mockAwsClient.getLaunchConfiguration(ONDEMAND_LAUNCH_CONFIG.getLaunchConfigurationName())) .thenReturn(ONDEMAND_LAUNCH_CONFIG); when(this.mockAwsClient.getAutoScalingGroup(GROUP_NAME)).thenReturn(groupAtT1); // one running instance returned on later call to get group members List<Instance> groupMembersAtT2 = ec2Instances(ec2Instance("i-1", "running")); when(this.mockAwsClient.getAutoScalingGroupMembers(GROUP_NAME)).thenReturn(groupMembersAtT2); List<Machine> machines = this.driver.listMachines(); assertThat(machines.size(), is(1)); assertThat(machines.get(0).getId(), is("i-1")); assertThat(machines.get(0).getMachineState(), is(MachineState.RUNNING)); }
public static boolean isDeployable(DeployConfiguration activeConfiguration, AutoScalingGroup autoScalingGroup, List<Ec2Instance> instances) { boolean canDeploy = false; // default calculatorF switch (activeConfiguration.getDeployStrategy()) { case KEEP_CAPACITY: canDeploy = new KeepCapacityStrategy().isDeployable(activeConfiguration, autoScalingGroup, instances); break; case DEFAULT: canDeploy = new DefaultDeployStrategy().isDeployable(activeConfiguration, autoScalingGroup, instances); break; case GUARANTEE_MINIMUM: canDeploy = new GuaranteeMinimumStrategy().isDeployable(activeConfiguration, autoScalingGroup, instances); break; case WHATEVER: canDeploy = new WhateverStrategy().isDeployable(activeConfiguration, autoScalingGroup, instances); break; case SPIN_AND_REMOVE: canDeploy = true; break; default: } return canDeploy; }
private AutoScalingGroup getAutoScalingGroup() { //there is no possibility to set custom name for AutoScalingGroup from CFT //that's why we have to determine created group name in code base on stack name //CloudFormation service uses next schema for AutoScalingGroup name //$CUSTOM_STACK_NAME-AutoScalingGroup-<some random string> Optional<AutoScalingGroup> asg = null; if (autoScalingGroup == null) { asg = autoScaling.describeAutoScalingGroups().getAutoScalingGroups().stream() .filter(autoScalingGroup -> autoScalingGroup.getAutoScalingGroupName() .startsWith(SystemUtils.getCloudFormationStackName() + "-AutoScalingGroup-")).findFirst(); autoScalingGroup = asg.orElseThrow(() -> new ConfigurationException("No appropriate AutoScalingGroup was found")); } return autoScalingGroup; }
/** * Convert from AWS ASG Instances to Turbine Instances * * @param asg * @return list of Turbine Instances (not AWS Instances) */ private List<Instance> getTurbineInstances(AutoScalingGroup asg) { String clusterName = asg.getTags() .stream() .filter(t -> t.getKey().equals(CLUSTER_TAG_KEY.get())) .findAny() .get().getValue(); List<com.amazonaws.services.autoscaling.model.Instance> awsInstances = asg.getInstances(); Collection<String> instanceIds = awsInstances.stream() .map(com.amazonaws.services.autoscaling.model.Instance::getInstanceId) .collect(Collectors.toSet()); DescribeInstancesRequest request = new DescribeInstancesRequest(); request.withInstanceIds(instanceIds); DescribeInstancesResult describeInstancesResult = ec2Client.describeInstances(request); List<Reservation> reservations = describeInstancesResult.getReservations(); List<Instance> turbineInstances = new ArrayList<>(); // add all instances from each of the reservations - after converting to Turbine instance reservations.stream() .flatMap(r -> r.getInstances().stream()) .filter(i -> !Strings.isNullOrEmpty(i.getPublicDnsName())) .map(i -> createTurbineInstance(clusterName, i)) .forEach(turbineInstances::add); return turbineInstances; }
public AutoScalingGroup createASGroup(CreateAutoScalingGroupRequest request) { logger.info("create auto scaling group, request={}", request); autoScaling.createAutoScalingGroup(request); DescribeAutoScalingGroupsResult result = autoScaling.describeAutoScalingGroups(new DescribeAutoScalingGroupsRequest().withAutoScalingGroupNames(request.getAutoScalingGroupName())); return result.getAutoScalingGroups().get(0); }
public List<AutoScalingGroup> listASGroups() { logger.info("list all auto scaling groups"); List<AutoScalingGroup> asGroups = new ArrayList<>(); String nextToken = null; while (true) { DescribeAutoScalingGroupsResult result = autoScaling.describeAutoScalingGroups(new DescribeAutoScalingGroupsRequest().withNextToken(nextToken)); asGroups.addAll(result.getAutoScalingGroups()); nextToken = result.getNextToken(); if (nextToken == null) break; } return asGroups; }
public AutoScalingGroup describeASGroup(String asGroupName) { logger.info("describe auto scaling group, name={}", asGroupName); List<AutoScalingGroup> groups = autoScaling.describeAutoScalingGroups(new DescribeAutoScalingGroupsRequest() .withAutoScalingGroupNames(asGroupName)) .getAutoScalingGroups(); if (groups.isEmpty()) return null; return groups.get(0); }
public void load() { String prefix = env.name + "-"; // find all AS group with prefix List<AutoScalingGroup> asGroups = AWS.as.listASGroups().stream() .filter(group -> group.getAutoScalingGroupName().startsWith(prefix)) .collect(Collectors.toList()); if (asGroups.isEmpty()) return; // load remote launch config in one request to maximize the speed List<String> launchConfigNames = asGroups.stream().map(AutoScalingGroup::getLaunchConfigurationName).collect(Collectors.toList()); Map<String, LaunchConfiguration> configs = AWS.as.describeLaunchConfigs(launchConfigNames); for (AutoScalingGroup remoteASGroup : asGroups) { String asGroupName = remoteASGroup.getAutoScalingGroupName(); String asGroupId = asGroupName.substring(prefix.length()); ASGroup asGroup = resources.find(ASGroup.class, asGroupId) .orElseGet(() -> resources.add(new ASGroup(asGroupId))); asGroup.remoteASGroup = remoteASGroup; asGroup.launchConfig.remoteLaunchConfig = configs.get(remoteASGroup.getLaunchConfigurationName()); asGroup.foundInRemote(); List<ScalingPolicy> remotePolicies = AWS.as.describeScalingPolicies(asGroupName); for (ScalingPolicy remotePolicy : remotePolicies) { String policyId = remotePolicy.getPolicyName(); AutoScalingPolicy policy = resources.find(AutoScalingPolicy.class, policyId) .orElseGet(() -> resources.add(new AutoScalingPolicy(policyId))); policy.remotePolicy = remotePolicy; policy.foundInRemote(); } } }
@Override public List<Instance> call() { AutoScalingGroup autoScalingGroup = new GetAutoScalingGroup(getAwsCredentials(), getRegion(), getClientConfig(), this.groupName).call(); try { return listGroupInstances(autoScalingGroup); } catch (Exception e) { throw new RuntimeException( String.format("failed waiting for auto scaling group members: %s", e.getMessage()), e); } }
@Override public AutoScalingGroup call() { DescribeAutoScalingGroupsRequest request = new DescribeAutoScalingGroupsRequest() .withAutoScalingGroupNames(this.groupName); DescribeAutoScalingGroupsResult result = getClient().getApi().describeAutoScalingGroups(request); List<AutoScalingGroup> autoScalingGroups = result.getAutoScalingGroups(); if (autoScalingGroups.isEmpty()) { throw new IllegalArgumentException(format("Auto Scaling Group '%s' doesn't exist in region '%s'.", this.groupName, getClient().getRegion())); } return getOnlyElement(autoScalingGroups); }
/** * Returns the machine instances in the Auto Scaling Group pool. * <p/> * For the case where {@code desiredCapacity} is greater than the number of * started instances, we produce a number of placeholder {@link Machine}s * (in {@code REQUESTED} state) for requested, but not yet acquired, * instances in an Auto Scaling Group. The number of produced placeholder * instances is the the difference between {@code desiredCapacity} and * {@code actualCapacity}. * <p/> * Rationale: the desired capacity of the AWS Auto Scaling Group may differ * from the actual number of instances in the group. If the desiredCapacity * of the Auto Scaling Group is greater than the actual number of instances * in the group, we should return placeholder Machines in {@code REQUESTED} * state for the missing instances. This prevents the {@link BaseCloudPool} * from regarding the scaling group too small and ordering new machines via * startMachines. * * @see com.elastisys.scale.cloudpool.commons.basepool.driver.CloudPoolDriver#listMachines() */ @Override public List<Machine> listMachines() throws CloudPoolDriverException { checkState(isConfigured(), "attempt to use unconfigured driver"); try { AutoScalingGroup group = this.client.getAutoScalingGroup(scalingGroupName()); int desiredCapacity = group.getDesiredCapacity(); // fetch actual scaling group members List<Instance> groupInstances = this.client.getAutoScalingGroupMembers(scalingGroupName()); List<Machine> acquiredMachines = groupInstances.stream().map(new InstanceToMachine()) .collect(Collectors.toList()); int actualCapacity = acquiredMachines.size(); // requested, but not yet allocated, machines int missingInstances = Math.max(desiredCapacity - actualCapacity, 0); LaunchConfiguration launchConfig = this.client.getLaunchConfiguration(group.getLaunchConfigurationName()); List<Machine> requestedInstances = pseudoMachines(missingInstances, launchConfig); List<Machine> pool = new ArrayList<>(); pool.addAll(acquiredMachines); pool.addAll(requestedInstances); return pool; } catch (Exception e) { throw new CloudPoolDriverException( format("failed to retrieve machines in cloud pool \"%s\", Auto Scaling Group \"%s\": %s", getPoolName(), scalingGroupName(), e.getMessage()), e); } }
public static AutoScalingGroup group(String name, LaunchConfiguration launchConfig, int desiredCapacity, Collection<com.amazonaws.services.ec2.model.Instance> ec2Instances) { AutoScalingGroup autoScalingGroup = new AutoScalingGroup().withAutoScalingGroupName(name) .withLaunchConfigurationName(launchConfig.getLaunchConfigurationName()) .withDesiredCapacity(desiredCapacity).withInstances(toAsInstances(ec2Instances)); return autoScalingGroup; }
/** * Sets up a fake {@link AutoScalingClient} with a fake pool containing both * instances that are members of the Auto Scaling Group and instances that * are not members. * * @param autoScalingGroupName * @param launchConfig * @param desiredCapacity * @param memberInstances * Auto Scaling Group members. * @param nonMemberInstances * EC2 instances that exist in the (fake) cloud but aren't * members of the Auto Scaling Group. */ private void setUpMockedAutoScalingGroup(String autoScalingGroupName, LaunchConfiguration launchConfig, int desiredCapacity, List<Instance> memberInstances, List<Instance> nonMemberInstances) { AutoScalingGroup autoScalingGroup = group(autoScalingGroupName, launchConfig, desiredCapacity, memberInstances); LOG.debug("setting up mocked group: {}", autoScalingGroup.getInstances().stream() .map(com.amazonaws.services.autoscaling.model.Instance::getInstanceId).collect(Collectors.toList())); // Lists.transform(autoScalingGroup.getInstances(), // AwsAutoScalingFunctions.toAutoScalingInstanceId())); when(this.mockAwsClient.getAutoScalingGroup(autoScalingGroupName)).thenReturn(autoScalingGroup); when(this.mockAwsClient.getLaunchConfiguration(launchConfig.getLaunchConfigurationName())) .thenReturn(launchConfig); when(this.mockAwsClient.getAutoScalingGroupMembers(autoScalingGroupName)).thenReturn(memberInstances); }
private void resumeAutoScalingPolicies(AuthenticatedContext ac, CloudStack stack) { for (Group instanceGroup : stack.getGroups()) { try { String asGroupName = cfStackUtil.getAutoscalingGroupName(ac, instanceGroup.getName(), ac.getCloudContext().getLocation().getRegion().value()); if (asGroupName != null) { AmazonAutoScalingClient amazonASClient = awsClient.createAutoScalingClient(new AwsCredentialView(ac.getCloudCredential()), ac.getCloudContext().getLocation().getRegion().value()); List<AutoScalingGroup> asGroups = amazonASClient.describeAutoScalingGroups(new DescribeAutoScalingGroupsRequest() .withAutoScalingGroupNames(asGroupName)).getAutoScalingGroups(); if (!asGroups.isEmpty()) { if (!asGroups.get(0).getSuspendedProcesses().isEmpty()) { amazonASClient.updateAutoScalingGroup(new UpdateAutoScalingGroupRequest() .withAutoScalingGroupName(asGroupName) .withMinSize(0) .withDesiredCapacity(0)); amazonASClient.resumeProcesses(new ResumeProcessesRequest().withAutoScalingGroupName(asGroupName)); } } } else { LOGGER.info("Autoscaling Group's physical id is null (the resource doesn't exist), it is not needed to resume scaling policies."); } } catch (AmazonServiceException e) { if (e.getErrorMessage().matches("Resource.*does not exist for stack.*") || e.getErrorMessage().matches("Stack '.*' does not exist.*")) { LOGGER.info(e.getMessage()); } else { throw e; } } } }
@Override public boolean calculate(DeployConfiguration activeConfiguration, AutoScalingGroup autoScalingGroup, long inService, long healthy, long inStandby) { if (activeConfiguration.useElbStatusCheck()) { return inService > autoScalingGroup.getDesiredCapacity()-1; } else { return healthy > autoScalingGroup.getDesiredCapacity()-1; } }
default boolean isDeployable(DeployConfiguration activeConfiguration, AutoScalingGroup autoScalingGroup, List<Ec2Instance> instances) { long healthyInstances = autoScalingGroup.getInstances().stream() .filter(i -> i.getLifecycleState().equals(LifecycleState.InService.toString())) .count(); long inStandbyInstances = autoScalingGroup.getInstances().stream() .filter(i -> i.getLifecycleState().equals(LifecycleState.Standby.toString())) .count(); long inServiceInstances = instances.stream().filter(i -> AwsState.INSERVICE.equals(i.getElbState())).count(); return this.calculate(activeConfiguration, autoScalingGroup, inServiceInstances, healthyInstances, inStandbyInstances); }
@Override public boolean calculate(DeployConfiguration activeConfiguration, AutoScalingGroup autoScalingGroup, long inService, long healthy, long inStandby) { if (activeConfiguration.useElbStatusCheck()) { return inService > activeConfiguration.getMinCapacity(); } else { return healthy > activeConfiguration.getMinCapacity(); } }
@Override public void execute() throws MojoExecutionException, MojoFailureException { DeployConfiguration deployConfiguration = new DeployConfiguration().withAutoScalingGroup(autoScalingGroupId); AwsAutoScalingDeployUtils asUtils = new AwsAutoScalingDeployUtils(region, deployConfiguration, getLog()); AutoScalingGroup asGroup = asUtils.getAutoScalingGroup(); if (asGroup.getInstances().isEmpty() && asGroup.getDesiredCapacity() == 0) { getLog().info("Adding 1 instance to auto scaling group with id " + autoScalingGroupId); asUtils.enableAsGroup(autoScalingGroupId); } }
private List<Ec2Instance> checkInstances(AwsAutoScalingDeployUtils awsDeployUtils, AutoScalingGroup asGroup, List<Ec2Instance> instances) { List<String> removedInstances = asGroup.getInstances().stream() .filter(i -> i.getLifecycleState().equalsIgnoreCase(AwsState.STANDBY.name())) .map(Instance::getInstanceId) .filter(awsDeployUtils::checkEc2Instance) .collect(Collectors.toList()); if (removedInstances != null && removedInstances.isEmpty()) { return instances.stream() .filter(i -> !removedInstances.contains(i.getInstanceId())) .collect(Collectors.toList()); } return instances; }
public void preDeploy(List<Ec2Instance> instances, AutoScalingGroup asGroup) throws MojoFailureException, MojoExecutionException { if (asGroup.getInstances().isEmpty()) { log.info("No instances found in autoscaling group, spinning new instance"); WaitForInstanceRequestExecutor.InstanceStatus instanceStatus = newInstance -> awsDeployUtils.checkInstanceInService(newInstance.getInstanceId()); awsDeployUtils.setDesiredCapacity(asGroup, asGroup.getDesiredCapacity() + 1); WaitForInstanceRequestExecutor waitForDeployedInstanceRequestExecutor = new WaitForInstanceRequestExecutor(log, 10); waitForDeployedInstanceRequestExecutor.executeRequest(asGroup, awsDeployUtils, instanceStatus); instances.addAll(awsDeployUtils.getInstancesForAutoScalingGroup(log, awsDeployUtils.getAutoScalingGroup())); } }
public void preDeploy(List<Ec2Instance> instances, AutoScalingGroup asGroup) throws MojoFailureException, MojoExecutionException { if (instances.isEmpty()) { throw new MojoFailureException("No instances in AS group." + activeConfiguration.getDeployStrategy()); } if (instances.stream().anyMatch(i -> !i.isReachable(activeConfiguration.getAwsPrivateIp(), activeConfiguration.getPort(), log))) { log.error("Error connecting to deploy module on some instances"); throw new MojoExecutionException("Error connecting to deploy module on some instances"); } if ((activeConfiguration.useElbStatusCheck() && instances.stream().noneMatch(i -> i.getElbState() == AwsState.INSERVICE)) || !activeConfiguration.useElbStatusCheck() && asGroup.getInstances().stream().noneMatch(i -> "InService".equals(i.getLifecycleState()))) { activeConfiguration.setDeployStrategy(DeployStrategyType.WHATEVER); log.info("No instances inService, using deploy strategy " + DeployStrategyType.WHATEVER); } if (shouldSpinNewInstance(awsDeployUtils, asGroup)) { WaitForInstanceRequestExecutor.InstanceStatus instanceStatus = newInstance -> !asGroup.getLoadBalancerNames().isEmpty() && awsDeployUtils.checkInstanceInServiceOnAllElb(newInstance, asGroup.getLoadBalancerNames()); awsDeployUtils.setDesiredCapacity(asGroup, asGroup.getDesiredCapacity() + 1); WaitForInstanceRequestExecutor waitForDeployedInstanceRequestExecutor = new WaitForInstanceRequestExecutor(log, 10); waitForDeployedInstanceRequestExecutor.executeRequest(asGroup, awsDeployUtils, instanceStatus); instances = awsDeployUtils.getInstancesForAutoScalingGroup(log, awsDeployUtils.getAutoScalingGroup()); } instances.sort(Comparator.comparingInt(o -> o.getElbState().ordinal())); if (instances.isEmpty()) { throw new MojoFailureException("No inService instances found in group " + activeConfiguration.getAutoScalingGroupId() + ". Nothing to do here, move along"); } if (!DeployStateStrategyFactory.isDeployable(activeConfiguration, asGroup, instances)) { throw new MojoExecutionException("Auto scaling group is not in a deployable state."); } if (activeConfiguration.isSticky()) { asGroup.getLoadBalancerNames().forEach(elbName -> awsDeployUtils.enableStickiness(elbName, activeConfiguration.getStickyPorts())); } }
public void postDeploy(AutoScalingGroup asGroup, Integer originalDesiredCapacity) { if (DeployStrategyType.KEEP_CAPACITY.equals(activeConfiguration.getDeployStrategy())) { awsDeployUtils.setDesiredCapacity(asGroup, originalDesiredCapacity); } if (activeConfiguration.isSticky()) { asGroup.getLoadBalancerNames().forEach(elbName -> awsDeployUtils.disableStickiness(elbName, activeConfiguration.getStickyPorts())); } }
@Test @Ignore public void testInStandByInstancesFirst() throws Exception { AutoScalingGroup asgroup = deployUtils.getAutoScalingGroup(); Assert.assertEquals(2, asgroup.getInstances().size()); List<Ec2Instance> instances = deployUtils.getInstancesForAutoScalingGroup(log, asgroup); Assert.assertEquals(2, instances.size()); }
public List<AbstractResource<?>> toAsGroups(List<AutoScalingGroup> autoScalingGroups, String accountId, Region region, DateTime dt) { List<AbstractResource<?>> resources = new ArrayList<>(); for (AutoScalingGroup autoScalingGroup : autoScalingGroups) { Ec2AutoScalingGroup ec2AutoScalingGroup = new Ec2AutoScalingGroup(); conf(ec2AutoScalingGroup, accountId, region, dt); ec2AutoScalingGroup.setResource(autoScalingGroup); resources.add(ec2AutoScalingGroup); } log.debug("{} auto scaling groups found via api and converted to Ec2AutoScalingGroup", resources.size()); return resources; }
@Test public void testGetPublicDnsForAutoScalingGroup() { String logicalId = "fake-logical-id"; String instanceId = "fake-instance-id"; String dnsName = "dns.name"; when(autoScalingClient.describeAutoScalingGroups( new DescribeAutoScalingGroupsRequest() .withAutoScalingGroupNames(logicalId) ) ).thenReturn( new DescribeAutoScalingGroupsResult() .withAutoScalingGroups( new AutoScalingGroup() .withInstances( new Instance() .withInstanceId(instanceId) ) ) ); when(ec2Client.describeInstances( new DescribeInstancesRequest() .withInstanceIds(instanceId) ) ).thenReturn( new DescribeInstancesResult() .withReservations( new Reservation() .withInstances( new com.amazonaws.services.ec2.model.Instance() .withPublicDnsName(dnsName) ) ) ); // invoke method under test List<String> results = autoScalingService.getPublicDnsForAutoScalingGroup(logicalId); assertEquals(1, results.size()); assertEquals(dnsName, results.get(0)); }
@Test public void getInstances() throws Exception { AutoScalingGroup groupWithTag1 = new AutoScalingGroup() .withTags(new TagDescription().withKey(TAG_KEY).withValue("Cluster1")) .withInstances(createMockInstance("id1"), createMockInstance("id2")); AutoScalingGroup groupWithTag2 = new AutoScalingGroup() .withTags(new TagDescription().withKey(TAG_KEY).withValue("Cluster2")) .withInstances(createMockInstance("id3"), createMockInstance("id4")); AutoScalingGroup groupWithoutTag = new AutoScalingGroup() .withTags(new TagDescription().withKey("WrongTag").withValue("Cluster3")) .withInstances(createMockInstance("id5"), createMockInstance("id6")); Set<String> badIds = Sets.newHashSet("id5", "id6"); DescribeAutoScalingGroupsResult result = new DescribeAutoScalingGroupsResult(); result.setAutoScalingGroups(Lists.newArrayList(groupWithTag1, groupWithTag2, groupWithoutTag)); when(asgClient.describeAutoScalingGroups(anyObject())).thenReturn(result); // mock the ec2 client request to get instance details when(ec2Client.describeInstances(any(DescribeInstancesRequest.class))).thenAnswer(m -> { DescribeInstancesRequest req = m.getArgumentAt(0, DescribeInstancesRequest.class); // make sure id5 and id6 didnt get requested. They dont have the right tag assertTrue(Sets.intersection(Sets.newHashSet(req.getInstanceIds()), badIds).isEmpty()); List<com.amazonaws.services.ec2.model.Instance> ec2Instances = req.getInstanceIds().stream() .map(id -> new com.amazonaws.services.ec2.model.Instance() .withInstanceId(id) .withTags(new Tag(TAG_KEY, "Unused")) .withState(new InstanceState().withName("running")) .withPublicDnsName("www.public.com")) .collect(Collectors.toList()); return new DescribeInstancesResult().withReservations(new Reservation().withInstances(ec2Instances)); }); Collection<Instance> instanceList = new AsgTagInstanceDiscovery(asgClient, ec2Client).getInstanceList(); assertNotNull(instanceList); assertEquals(4, instanceList.size()); Set<String> validClusters = Sets.newHashSet("Cluster1", "Cluster2"); for (Instance i : instanceList) { assertTrue(validClusters.contains(i.getCluster())); } }
public static void main( String[] args ) throws IOException { final String env = "prod"; AWSCredentials credentials = new PropertiesCredentials( ShutdownWorkers.class.getResourceAsStream( "/AwsCredentials.properties" ) ); try { // Scalo a zero int min = 0; int desired = 0; int max = 0; AmazonAutoScaling as = new AmazonAutoScalingClient(credentials); as.setEndpoint("autoscaling.eu-west-1.amazonaws.com"); DescribeAutoScalingGroupsResult dasgres = as.describeAutoScalingGroups(); List<AutoScalingGroup> lasg = dasgres.getAutoScalingGroups(); for (AutoScalingGroup asg : lasg) { if(asg.getAutoScalingGroupName().equals("asg-kopjra-prod-workers")){ desired = asg.getDesiredCapacity(); max = asg.getMaxSize(); min = asg.getMinSize(); break; } } UpdateAutoScalingGroupRequest uasgr = new UpdateAutoScalingGroupRequest(); uasgr.setAutoScalingGroupName("asg-kopjra-prod-workers"); uasgr.setDesiredCapacity(0); uasgr.setMaxSize(0); uasgr.setMinSize(0); as.updateAutoScalingGroup(uasgr); System.out.println("Done: workers shutting down!"); System.out.println("When you run the StartupWorkers, remember to use the following parameters: "+min+" "+max+" "+desired); } catch (AmazonServiceException ase) { System.err.println( "AmazonServiceException" ); } catch (AmazonClientException ace) { System.err.println( "AmazonClientException" ); } catch (Exception e){ System.err.println( "OtherException" ); } }
@VisibleForTesting Optional<String> getReconnectableClusterId() throws IOException { // List ASGs with Tag of cluster name final Tag clusterNameTag = new Tag() .withKey(CLUSTER_NAME_ASG_TAG) .withValue(this.clusterName); final List<AutoScalingGroup> autoScalingGroups = this.awsSdkClient.getAutoScalingGroupsWithTag(clusterNameTag); // If no auto scaling group is found, we don't have an existing cluster to connect to if (autoScalingGroups.size() == 0) { return Optional.absent(); } // If more than 0 auto scaling groups are found, validate the setup if (autoScalingGroups.size() != 2) { throw new IOException("Expected 2 auto scaling groups (1 each for master and workers) but found: " + autoScalingGroups.size()); } // Retrieve cluster information from ASGs Optional<String> clusterId = Optional.absent(); Optional<AutoScalingGroup> masterAsg = Optional.absent(); Optional<AutoScalingGroup> workersAsg = Optional.absent(); for (TagDescription tagDescription : autoScalingGroups.get(0).getTags()) { LOGGER.info("Found tag: " + tagDescription); if (tagDescription.getKey().equalsIgnoreCase(CLUSTER_ID_ASG_TAG)) { clusterId = Optional.of(tagDescription.getValue()); } if (tagDescription.getKey().equalsIgnoreCase(ASG_TYPE_ASG_TAG)) { if (tagDescription.getValue().equalsIgnoreCase(ASG_TYPE_MASTER)) { masterAsg = Optional.of(autoScalingGroups.get(0)); workersAsg = Optional.of(autoScalingGroups.get(1)); } else { masterAsg = Optional.of(autoScalingGroups.get(1)); workersAsg = Optional.of(autoScalingGroups.get(0)); } } } if (!clusterId.isPresent()) { throw new IOException("Found 2 auto scaling group names for: " + this.clusterName + " but tags seem to be corrupted, hence could not determine cluster id"); } if (!masterAsg.isPresent() || !workersAsg.isPresent()) { throw new IOException("Found 2 auto scaling group names for: " + this.clusterName + " but tags seem to be corrupted, hence could not determine master and workers ASG"); } // Get Master and Workers launch config name and auto scaling group name this.masterAutoScalingGroupName = masterAsg.get().getAutoScalingGroupName(); this.masterLaunchConfigName = masterAsg.get().getLaunchConfigurationName(); this.workerAutoScalingGroupName = workersAsg.get().getAutoScalingGroupName(); this.workerLaunchConfigName = workersAsg.get().getLaunchConfigurationName(); LOGGER.info("Trying to find cluster master public ip"); this.masterPublicIp = getMasterPublicIp(); LOGGER.info("Master public ip: "+ this.masterPublicIp); return clusterId; }
@BeforeClass public void setUp() throws Exception { // Mock AWS SDK calls MockitoAnnotations.initMocks(this); PowerMockito.whenNew(AWSSdkClient.class).withAnyArguments().thenReturn(awsSdkClient); Mockito.doNothing() .when(awsSdkClient) .createSecurityGroup(Mockito.anyString(), Mockito.anyString()); Mockito.doReturn(Lists.<AvailabilityZone>newArrayList(availabilityZone)) .when(awsSdkClient) .getAvailabilityZones(); Mockito.doReturn("dummy") .when(awsSdkClient) .createKeyValuePair(Mockito.anyString()); Mockito.doReturn(Lists.<AutoScalingGroup>newArrayList(masterASG, workerASG)) .when(awsSdkClient) .getAutoScalingGroupsWithTag(Mockito.any(Tag.class)); Mockito.doReturn(Lists.<Instance>newArrayList(instance)) .when(awsSdkClient) .getInstancesForGroup(Mockito.anyString(), Mockito.anyString()); Mockito.doReturn(Lists.<S3ObjectSummary>newArrayList()) .when(awsSdkClient) .listS3Bucket(Mockito.anyString(), Mockito.anyString()); Mockito.doNothing() .when(awsSdkClient) .addPermissionsToSecurityGroup(Mockito.any(String.class), Mockito.any(String.class), Mockito.any(String.class), Mockito.any(Integer.class), Mockito.any(Integer.class)); Mockito.doNothing() .when(awsSdkClient) .createAutoScalingGroup(Mockito.any(String.class), Mockito.any(String.class), Mockito.any(Integer.class), Mockito.any(Integer.class), Mockito.any(Integer.class), Mockito.any(Optional.class), Mockito.any(Optional.class), Mockito.any(Optional.class), Mockito.any(Optional.class), Mockito.any(Optional.class), Mockito.any(Optional.class), Mockito.any(List.class)); Mockito.doNothing() .when(awsSdkClient) .createLaunchConfig(Mockito.any(String.class), Mockito.any(String.class), Mockito.any(String.class), Mockito.any(String.class), Mockito.any(String.class), Mockito.any(Optional.class), Mockito.any(Optional.class), Mockito.any(Optional.class), Mockito.any(Optional.class), Mockito.any(Optional.class), Mockito.any(String.class)); Mockito .doNothing() .when(awsSdkClient) .deleteAutoScalingGroup(Mockito.any(String.class), Mockito.any(boolean.class)); Mockito .doNothing() .when(awsSdkClient) .deleteLaunchConfiguration(Mockito.any(String.class)); Mockito.doNothing() .when(awsSdkClient) .addPermissionsToSecurityGroup(Mockito.any(String.class), Mockito.any(String.class), Mockito.any(String.class), Mockito.any(Integer.class), Mockito.any(Integer.class)); // Local test Zookeeper final TestingServer testingZKServer = this.closer.register(new TestingServer(-1)); LOG.info("Testing ZK Server listening on: " + testingZKServer.getConnectString()); this.curatorFramework = TestHelper.createZkClient(testingZKServer, this.closer); // Load configuration final URL url = GobblinAWSClusterLauncherTest.class.getClassLoader().getResource( GobblinAWSClusterLauncherTest.class.getSimpleName() + ".conf"); Assert.assertNotNull(url, "Could not find resource " + url); this.config = ConfigFactory.parseURL(url) .withValue("gobblin.cluster.zk.connection.string", ConfigValueFactory.fromAnyRef(testingZKServer.getConnectString())) .resolve(); this.helixClusterName = this.config.getString(GobblinClusterConfigurationKeys.HELIX_CLUSTER_NAME_KEY); final String zkConnectionString = this.config.getString(GobblinClusterConfigurationKeys.ZK_CONNECTION_STRING_KEY); this.helixManager = HelixManagerFactory .getZKHelixManager(this.config.getString(GobblinClusterConfigurationKeys.HELIX_CLUSTER_NAME_KEY), TestHelper.TEST_HELIX_INSTANCE_NAME, InstanceType.CONTROLLER, zkConnectionString); // Gobblin AWS Cluster Launcher to test this.gobblinAwsClusterLauncher = new GobblinAWSClusterLauncher(this.config); }
@Override public AutoScalingGroup getAutoScalingGroup(String autoScalingGroupName) throws AmazonClientException { checkArgument(isConfigured(), "can't use client before it's configured"); return new GetAutoScalingGroup(awsCredentials(), region(), clientConfig(), autoScalingGroupName).call(); }
@Override public AutoScalingGroup getAutoScalingGroup(String autoScalingGroupName) { return group(autoScalingGroupName, this.launchConfig, this.desiredCapacity, this.memberInstances); }
@RequestMapping(value = "/autoscalinggroup", method = RequestMethod.GET) @ResponseBody public List<AutoScalingGroup> listAutoScalingGroups(@RequestParam("accessKey") String accessKey, @RequestParam("secretKey") String secretKey) { return awsec2Service.describeAmazonAutoScalingGroups(awsCredentialsFactory.createSimpleAWSCredentials(accessKey, secretKey)); }