package core.aws.local.as; import com.amazonaws.services.cloudwatch.model.ComparisonOperator; import core.aws.env.Environment; import core.aws.local.DependencyResolvers; import core.aws.local.LocalResourceLoader; import core.aws.local.ResourceNode; import core.aws.local.ec2.EBSBuilder; import core.aws.resource.Resources; import core.aws.resource.as.ASGroup; import core.aws.resource.as.AutoScalingPolicy; import core.aws.resource.ec2.InstanceProfile; import core.aws.resource.ec2.KeyPair; import core.aws.resource.ec2.SecurityGroup; import core.aws.resource.elb.ELB; import core.aws.resource.vpc.Subnet; import core.aws.util.Asserts; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; /** * @author neo */ public class ASGroupLoader implements LocalResourceLoader { @Override public void load(ResourceNode node, Resources resources, DependencyResolvers resolvers, Environment env) { String imageId = node.requiredString("ami"); String instanceType = node.requiredString("instance-type"); String securityGroupId = node.requiredString("security-group"); String subnetId = node.requiredString("subnet"); Map<?, ?> capacity = node.mapField("capacity"); int minSize = (int) Asserts.notNull(capacity.get("min"), "min is required for capacity"); int maxSize = (int) Asserts.notNull(capacity.get("max"), "max is required for capacity"); int desiredSize = (int) Asserts.notNull(capacity.get("desired"), "desired is required for capacity"); Optional<String> elbId = node.getString("elb"); Optional<String> instanceProfileId = node.getString("instance-profile"); ASGroup asGroup = resources.add(new ASGroup(node.id)); asGroup.launchConfig.instanceType = instanceType; asGroup.launchConfig.ebs = new EBSBuilder().build(node.mapField("ebs")); asGroup.launchConfig.keyPair = resources.find(KeyPair.class, node.id) .orElseGet(() -> resources.add(new KeyPair(node.id, env.name + ":" + node.id))); asGroup.minSize = minSize; asGroup.maxSize = maxSize; asGroup.desiredSize = desiredSize; resolvers.add(node, () -> { asGroup.launchConfig.securityGroup = resources.get(SecurityGroup.class, securityGroupId); asGroup.launchConfig.ami = resources.ami(env.region, imageId); instanceProfileId.ifPresent(id -> asGroup.launchConfig.instanceProfile = resources.get(InstanceProfile.class, id)); elbId.ifPresent(id -> asGroup.elb = resources.get(ELB.class, id)); asGroup.subnet = resources.get(Subnet.class, subnetId); }); List<AutoScalingPolicy> policies = loadPolicies(node); for (AutoScalingPolicy policy : policies) { resources.add(policy); policy.asGroup = asGroup; } } @SuppressWarnings("unchecked") private List<AutoScalingPolicy> loadPolicies(ResourceNode node) { final List<AutoScalingPolicy> policies = new ArrayList<>(); Object scale = node.field("scale"); if (scale instanceof Map) { policies.add(scale(node.id, (Map<String, Object>) scale)); } else if (scale instanceof List) { policies.addAll(((List<Map<String, Object>>) scale).stream() .map(rule -> scale(node.id, rule)) .collect(Collectors.toList())); } return policies; } public AutoScalingPolicy scale(String resourceId, Map<String, Object> params) { String name = (String) Asserts.notNull(params.get("name"), "name is required for scale"); String cpu = (String) Asserts.notNull(params.get("cpu"), "cpu is required for scale"); String last = (String) Asserts.notNull(params.get("last"), "last is required for scale"); String adjustment = (String) Asserts.notNull(params.get("adjustment"), "adjustment is required for scale"); return createPolicy(resourceId, name, cpu, last, adjustment); } AutoScalingPolicy createPolicy(String resourceId, String name, String cpu, String last, String adjustment) { AutoScalingPolicy policy = new AutoScalingPolicy(resourceId + "-" + name); Asserts.isTrue(cpu.matches("[>|<]=\\d+%"), "cpu should be like >=80%"); if (cpu.startsWith(">=")) { policy.comparisonOperator = ComparisonOperator.GreaterThanOrEqualToThreshold; } else { policy.comparisonOperator = ComparisonOperator.LessThanOrEqualToThreshold; } policy.cpuUtilizationPercentage = Integer.parseInt(cpu.substring(2, cpu.length() - 1)); Asserts.isTrue(last.endsWith("min"), "last should be like 3min"); policy.lastMinutes = Integer.parseInt(last.substring(0, last.length() - 3)); Asserts.isTrue(adjustment.endsWith("%"), "adjustment should be like 15%"); policy.adjustmentPercentage = Integer.parseInt(adjustment.substring(0, adjustment.length() - 1)); return policy; } }