package core.aws.client;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.autoscaling.AmazonAutoScaling;
import com.amazonaws.services.autoscaling.AmazonAutoScalingClientBuilder;
import com.amazonaws.services.autoscaling.model.AutoScalingGroup;
import com.amazonaws.services.autoscaling.model.CreateAutoScalingGroupRequest;
import com.amazonaws.services.autoscaling.model.CreateLaunchConfigurationRequest;
import com.amazonaws.services.autoscaling.model.CreateOrUpdateTagsRequest;
import com.amazonaws.services.autoscaling.model.DeleteAutoScalingGroupRequest;
import com.amazonaws.services.autoscaling.model.DeleteLaunchConfigurationRequest;
import com.amazonaws.services.autoscaling.model.DeletePolicyRequest;
import com.amazonaws.services.autoscaling.model.DescribeAutoScalingGroupsRequest;
import com.amazonaws.services.autoscaling.model.DescribeAutoScalingGroupsResult;
import com.amazonaws.services.autoscaling.model.DescribeLaunchConfigurationsRequest;
import com.amazonaws.services.autoscaling.model.DescribePoliciesRequest;
import com.amazonaws.services.autoscaling.model.LaunchConfiguration;
import com.amazonaws.services.autoscaling.model.PutScalingPolicyRequest;
import com.amazonaws.services.autoscaling.model.ScalingPolicy;
import com.amazonaws.services.autoscaling.model.Tag;
import com.amazonaws.services.autoscaling.model.TerminateInstanceInAutoScalingGroupRequest;
import com.amazonaws.services.autoscaling.model.UpdateAutoScalingGroupRequest;
import core.aws.util.Exceptions;
import core.aws.util.Maps;
import core.aws.util.Runner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author neo
*/
public class AutoScaling {
public final AmazonAutoScaling autoScaling;
private final Logger logger = LoggerFactory.getLogger(getClass());
public AutoScaling(AWSCredentialsProvider credentials, Regions region) {
autoScaling = AmazonAutoScalingClientBuilder.standard().withRegion(region).withCredentials(credentials).build();
}
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 LaunchConfiguration createLaunchConfig(CreateLaunchConfigurationRequest request) throws Exception {
return new Runner<LaunchConfiguration>()
.retryInterval(Duration.ofSeconds(5))
.maxAttempts(3)
.retryOn(e -> e instanceof AmazonServiceException)
.run(() -> {
logger.info("create launch config, request={}", request);
autoScaling.createLaunchConfiguration(request);
return describeLaunchConfig(request.getLaunchConfigurationName());
});
}
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 Map<String, LaunchConfiguration> describeLaunchConfigs(List<String> launchConfigNames) {
if (launchConfigNames.isEmpty()) throw new Error("launchConfigNames must not be empty");
logger.info("describe launch configs, names={}", launchConfigNames);
Map<String, LaunchConfiguration> results = Maps.newHashMap();
autoScaling.describeLaunchConfigurations(new DescribeLaunchConfigurationsRequest()
.withLaunchConfigurationNames(launchConfigNames))
.getLaunchConfigurations()
.forEach(config -> results.put(config.getLaunchConfigurationName(), config));
if (results.size() != launchConfigNames.size())
throw Exceptions.error("some launch config does not exist, foundNames={}", results.keySet());
return results;
}
public LaunchConfiguration describeLaunchConfig(String launchConfigName) {
logger.info("describe launch config, name={}", launchConfigName);
return autoScaling.describeLaunchConfigurations(new DescribeLaunchConfigurationsRequest()
.withLaunchConfigurationNames(launchConfigName))
.getLaunchConfigurations().get(0);
}
public List<ScalingPolicy> describeScalingPolicies(String asGroupName) {
logger.info("describe auto scaling policies, asGroupName={}", asGroupName);
return autoScaling.describePolicies(new DescribePoliciesRequest().withAutoScalingGroupName(asGroupName)).getScalingPolicies();
}
public void updateASGroup(UpdateAutoScalingGroupRequest request) throws Exception {
new Runner<>()
.retryInterval(Duration.ofSeconds(5))
.maxAttempts(3)
.retryOn(e -> e instanceof AmazonServiceException)
.run(() -> {
logger.info("update auto scaling group, request={}", request);
autoScaling.updateAutoScalingGroup(request);
return null;
});
}
public String createPolicy(PutScalingPolicyRequest request) {
logger.info("create scaling policy, request={}", request);
return autoScaling.putScalingPolicy(request).getPolicyARN();
}
public void deletePolicy(String asGroupName, String policyName) {
logger.info("delete scaling policy, asGroup={}, policy={}", asGroupName, policyName);
autoScaling.deletePolicy(new DeletePolicyRequest()
.withAutoScalingGroupName(asGroupName)
.withPolicyName(policyName));
}
public void updateTag(String asGroupName, Tag tag) {
logger.info("update auto scaling group tag, asGroup={}, key={}, value={}", asGroupName, tag.getKey(), tag.getValue());
tag.withResourceId(asGroupName).withResourceType("auto-scaling-group");
autoScaling.createOrUpdateTags(new CreateOrUpdateTagsRequest().withTags(tag));
}
public void deleteLaunchConfig(String launchConfigName) {
logger.info("delete launch config, name={}", launchConfigName);
autoScaling.deleteLaunchConfiguration(new DeleteLaunchConfigurationRequest()
.withLaunchConfigurationName(launchConfigName));
}
public void terminateInstancesInASGroup(List<String> instanceIds, boolean decrementDesiredCapacity) {
logger.info("terminate instances in auto scaling group, instanceIds={}, decrementDesiredCapacity={}", instanceIds, decrementDesiredCapacity);
for (String instanceId : instanceIds) {
try {
autoScaling.terminateInstanceInAutoScalingGroup(new TerminateInstanceInAutoScalingGroupRequest()
.withInstanceId(instanceId)
.withShouldDecrementDesiredCapacity(decrementDesiredCapacity));
} catch (AmazonClientException e) {
logger.warn("failed to terminate instance in auto scaling group, it could be already terminated by auto scaling group, instanceId={}", instanceId, e);
}
}
}
public void deleteAutoScalingGroup(String asGroupName) {
logger.info("delete auto scaling group, name={}", asGroupName);
autoScaling.deleteAutoScalingGroup(new DeleteAutoScalingGroupRequest()
.withAutoScalingGroupName(asGroupName)
.withForceDelete(true));
}
}