package core.aws.plan.ec2;
import com.amazonaws.services.ec2.model.IpPermission;
import com.amazonaws.services.ec2.model.UserIdGroupPair;
import core.aws.plan.Planner;
import core.aws.resource.ec2.SecurityGroup;
import core.aws.task.ec2.CreateSGRuleTask;
import core.aws.task.ec2.CreateSGTask;
import core.aws.task.ec2.DeleteSGRuleTask;
import core.aws.task.ec2.DeleteSGTask;
import core.aws.task.vpc.CreateVPCTask;
import core.aws.task.vpc.DeleteVPCTask;
import core.aws.util.StreamHelper;
import core.aws.workflow.Task;
import core.aws.workflow.Tasks;
import java.util.HashSet;
import java.util.Set;
/**
* @author neo
*/
public class SGTaskPlanner extends Planner {
public SGTaskPlanner(Tasks tasks) {
super(tasks);
}
@Override
public void plan() {
linkCreateTasks();
linkDeleteTasks();
removeUnnecessaryDeleteRuleTasks();
}
private void removeUnnecessaryDeleteRuleTasks() {
Set<DeleteSGRuleTask> removedTasks = new HashSet<>();
for (DeleteSGRuleTask deleteRuleTask : all(DeleteSGRuleTask.class)) {
Set<Task> backwardDependencies = deleteRuleTask.backwardDependencies;
if (backwardDependencies.size() == 1) {
DeleteSGTask deleteTask = (DeleteSGTask) backwardDependencies.stream().reduce(StreamHelper.onlyOne()).get();
// if only delete group task depends on delete its own rule task, we don't need delete rule task
if (deleteRuleTask.resource == deleteTask.resource) {
deleteTask.unlink(deleteRuleTask);
removedTasks.add(deleteRuleTask);
}
}
}
tasks.removeAll(removedTasks);
}
private void linkCreateTasks() {
all(CreateSGTask.class).stream()
.filter(sgTask -> sgTask.resource.vpc != null)
.forEach(sgTask -> find(CreateVPCTask.class).ifPresent(sgTask::dependsOn));
for (CreateSGRuleTask ruleTask : all(CreateSGRuleTask.class)) {
ruleTask.addedIngressRules.forEach((protocol, sources) -> sources.forEach(source -> {
final SecurityGroup sourceSG = source.securityGroup;
if (sourceSG != null) {
find(CreateSGTask.class, sourceSG)
.ifPresent(ruleTask::dependsOn);
}
}));
}
}
private void linkDeleteTasks() {
all(DeleteSGRuleTask.class)
.forEach(this::linkDeleteRuleTask);
for (DeleteSGTask sgTask : all(DeleteSGTask.class)) {
if (sgTask.resource.remoteSecurityGroup.getVpcId() != null) {
find(DeleteVPCTask.class).ifPresent(task -> task.dependsOn(sgTask));
}
}
}
private void linkDeleteRuleTask(DeleteSGRuleTask ruleTask) {
for (IpPermission rule : ruleTask.deletedIngressRules) {
for (UserIdGroupPair userIdGroup : rule.getUserIdGroupPairs()) {
final String sourceSGId = userIdGroup.getGroupId();
all(DeleteSGTask.class).stream()
.filter(task -> sourceSGId.equals(task.resource.remoteSecurityGroup.getGroupId()))
.findAny().ifPresent(task -> task.dependsOn(ruleTask));
}
}
}
}