package core.aws.resource.ec2;
import com.amazonaws.services.ec2.model.IpPermission;
import com.amazonaws.services.ec2.model.IpRange;
import core.aws.resource.Resource;
import core.aws.resource.ResourceStatus;
import core.aws.resource.Resources;
import core.aws.resource.vpc.VPC;
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.ec2.DescribeSGTask;
import core.aws.util.Asserts;
import core.aws.util.ToStringHelper;
import core.aws.workflow.Tasks;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author neo
*/
public class SecurityGroup extends Resource {
private final Map<Protocol, List<Source>> ingressRules = new HashMap<>();
public com.amazonaws.services.ec2.model.SecurityGroup remoteSecurityGroup;
public String name;
public VPC vpc;
public SecurityGroup(String id) {
super(id);
}
@Override
public void validate(Resources resources) {
if (status == ResourceStatus.LOCAL_REMOTE) {
Asserts.equals(vpc.status, ResourceStatus.LOCAL_REMOTE, "inconsistent state, security group refers to vpc not created");
Asserts.isTrue(vpc.remoteVPC.getVpcId().equals(remoteSecurityGroup.getVpcId()), "sg is in different vpc");
}
if (status == ResourceStatus.LOCAL_ONLY) {
Asserts.isTrue(name.length() <= 255, "max length of sg name is 255");
Asserts.isTrue(name.matches("[a-zA-Z0-9\\-\\:]+"), "sg name can only contain alphanumeric, '-' and ':'");
}
}
@Override
protected void createTasks(Tasks tasks) {
CreateSGTask createTask = tasks.add(new CreateSGTask(this));
CreateSGRuleTask createRuleTask = tasks.add(new CreateSGRuleTask(this, ingressRules));
createRuleTask.dependsOn(createTask);
}
@Override
protected void updateTasks(Tasks tasks) {
SecurityGroupRuleHelper helper = new SecurityGroupRuleHelper(ingressRules, remoteSecurityGroup.getIpPermissions());
List<IpPermission> deletedIngressRules = helper.findDeletedIngressRules();
if (!deletedIngressRules.isEmpty()) {
tasks.add(new DeleteSGRuleTask(this, deletedIngressRules));
}
Map<Protocol, List<Source>> addedIngressRules = helper.findAddedIngressRules();
if (!addedIngressRules.isEmpty()) {
tasks.add(new CreateSGRuleTask(this, addedIngressRules));
}
}
@Override
protected void describeTasks(Tasks tasks) {
tasks.add(new DescribeSGTask(this));
}
@Override
protected void deleteTasks(Tasks tasks) {
DeleteSGTask deleteTask = tasks.add(new DeleteSGTask(this));
DeleteSGRuleTask deleteRuleTask = tasks.add(new DeleteSGRuleTask(this, remoteSecurityGroup.getIpPermissions()));
deleteTask.dependsOn(deleteRuleTask);
}
public void addIngressRule(Protocol protocol, Source source) {
ingressRules.computeIfAbsent(protocol, key -> new ArrayList<>())
.add(source);
}
@Override
public String toString() {
return new ToStringHelper(this)
.add(id)
.add(status)
.add("name", name)
.toString();
}
public static class Source {
public SecurityGroup securityGroup;
public IpRange ipRange;
@Override
public String toString() {
return new ToStringHelper(this)
.addIfNotNull(securityGroup == null ? null : securityGroup.id)
.addIfNotNull(ipRange)
.toString();
}
}
}