package tw.com.repository; import com.amazonaws.services.ec2.model.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import tw.com.exceptions.CfnAssistException; import tw.com.exceptions.WrongNumberOfInstancesException; import tw.com.providers.CloudClient; import tw.com.providers.SavesFile; import java.io.IOException; import java.net.InetAddress; import java.util.*; import java.util.stream.Stream; import static java.lang.String.format; public class CloudRepository { private static final Logger logger = LoggerFactory.getLogger(CloudRepository.class); private CloudClient cloudClient; private Map<String,Subnet> subnetsCache = null; // id -> Subnet private List<Address> addressCache = null; private List<SecurityGroup> groupsCache = null; private List<Instance> instancesCache = null; private List<RouteTable> routeTableCache = null; private List<NetworkAcl> aclsCache = null; private Map<String, AvailabilityZone> zones = null; private Map<String,String> subnetToVpc; // subnet id -> vpc id private Map<String,String> instanceToVpc; // instance id -> vpc id public CloudRepository(CloudClient cloudClient) { this.cloudClient = cloudClient; subnetToVpc = new HashMap<>(); instanceToVpc = new HashMap<>(); } public List<Subnet> getSubnetsForVpc(String vpcId) { loadSubnets(); List<Subnet> filtered = new LinkedList<>(); for (Subnet subnet : subnetsCache.values()) { String subnetVpcId = subnet.getVpcId(); if (subnetVpcId!=null) { if (subnetVpcId.equals(vpcId)) { filtered.add(subnet); } } } return filtered; } public Subnet getSubnetById(String subnetId) { loadSubnets(); return subnetsCache.get(subnetId); } public List<Vpc> getAllVpcs() { // TODO Cache return cloudClient.getVpcs(); } public List<Instance> getInstancesForSubnet(String subnetId) { loadInstances(); List<Instance> result = new LinkedList<>(); for(Instance i : instancesCache) { String instanceSubnetId = i.getSubnetId(); if (instanceSubnetId!=null) { if (instanceSubnetId.equals(subnetId)) { result.add(i); } } } return result; } public SecurityGroup getSecurityGroupByName(String groupName) throws CfnAssistException { loadGroups(); for(SecurityGroup group : groupsCache) { if (group.getGroupName().equals(groupName)) { return group; } } throw new CfnAssistException(format("Failed to find SecurityGroup with name '%s'", groupName)); } public SecurityGroup getSecurityGroupById(String groupId) throws CfnAssistException { loadGroups(); for(SecurityGroup group : groupsCache) { if (group.getGroupId().equals(groupId)) { return group; } } throw new CfnAssistException(format("Failed to find SecurityGroup with id '%s'", groupId)); } public List<SecurityGroup> getSecurityGroupsFor(String vpcId) { loadGroups(); List<SecurityGroup> groups = new LinkedList<>(); for(SecurityGroup group : groupsCache) { if (group.getVpcId().equals(vpcId)) { groups.add(group); } } return groups; } public Instance getInstanceById(String instanceId) throws CfnAssistException { loadInstances(); for(Instance i : instancesCache) { if (i.getInstanceId().equals(instanceId)) { return i; } } throw new CfnAssistException(format("Failed to find Instance with id '%s'", instanceId)); } public List<Address> getEIPForVPCId(String vpcId) throws CfnAssistException { loadAddresses(); // find the instance each address is associated with and then check the VPC ID on the instance List<Address> filtered = new LinkedList<>(); for(Address address : addressCache) { String instanceId = address.getInstanceId(); if (instanceId!=null) { String instanceVpcId = getVpcIdForInstance(instanceId); if (instanceVpcId.equals(vpcId)) { filtered.add(address); } } } return filtered; } private String getVpcIdForInstance(String instanceId) throws CfnAssistException { if (!instanceToVpc.containsKey(instanceId)) { Instance instance = getInstanceById(instanceId); String instanceVpc = instance.getVpcId(); //String instanceVpc = getVpcForSubnet(instance.getSubnetId()); instanceToVpc.put(instanceId, instanceVpc); } return instanceToVpc.get(instanceId); } public List<NetworkAcl> getALCsForVPC(String vpcId) { loadACLs(); List<NetworkAcl> result = new LinkedList<>(); for (NetworkAcl acl : aclsCache) { if (acl.getVpcId().equals(vpcId)) { result.add(acl); } } return result; } public List<RouteTable> getRouteTablesForVPC(String vpcId) { loadRouteTables(); List<RouteTable> result = new LinkedList<>(); for(RouteTable table : routeTableCache) { if (table.getVpcId().equals(vpcId)) { result.add(table); } } return result; } private void loadRouteTables() { if (routeTableCache==null) { routeTableCache = cloudClient.getRouteTables(); } } private void loadGroups() { if (groupsCache==null) { groupsCache = cloudClient.getSecurityGroups(); } } private void loadInstances() { if (instancesCache==null) { instancesCache = cloudClient.getInstances(); } } private void loadACLs() { if (aclsCache==null) { aclsCache = cloudClient.getACLs(); } } private void loadAddresses() { if (addressCache==null) { addressCache = cloudClient.getEIPs(); } } private void loadSubnets() { if (subnetsCache==null) { List<Subnet> results = cloudClient.getAllSubnets(); subnetsCache = new HashMap<>(); for(Subnet subnet : results) { subnetsCache.put(subnet.getSubnetId(), subnet); String vpc = subnet.getVpcId(); if (vpc!=null) { subnetToVpc.put(subnet.getSubnetId(), vpc); } } } } public void updateAddIpAndPortToSecGroup(String groupId, InetAddress address, Integer port) { cloudClient.addIpToSecGroup(groupId, port, address); } public void updateRemoveIpAndPortFromSecGroup(String groupId, InetAddress address, Integer port) { cloudClient.deleteIpFromSecGroup(groupId, port, address); } public List<Tag> getTagsForInstance(String instanceId) throws WrongNumberOfInstancesException { Instance instance = cloudClient.getInstanceById(instanceId); return instance.getTags(); } public Map<String, AvailabilityZone> getZones(String regionName) { initAvailabilityZones(regionName); return zones; } private Map<String, AvailabilityZone> initAvailabilityZones(String regionName) { if (zones==null) { zones = cloudClient.getAvailabilityZones(regionName); } return zones; } public KeyPair createKeyPair(String keypairName, SavesFile savesFile, String filename) throws CfnAssistException { KeyPair pair = cloudClient.createKeyPair(keypairName); logger.info("Saving private key to " + filename); savesFile.save(filename, pair.getKeyMaterial()); try { savesFile.ownerOnlyPermisssion(filename); } catch (IOException ioException) { throw new CfnAssistException("Unable to change permission on file "+ filename, ioException); } return pair; } public String getIpFor(String eipAllocationId) { logger.info("Find EIP for " + eipAllocationId); List<Address> addresses = cloudClient.getEIPs(); logger.info(format("Found %s addresses", addresses.size())); Stream<Address> filtered = addresses.stream().filter(address -> eipAllocationId.equals(address.getAllocationId())); Optional<Address> result = filtered.findFirst(); result.ifPresent(found -> logger.info("Found address "+found)); return result.isPresent() ? result.get().getPublicIp() : ""; } }