package com.clouck.util; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.amazonaws.services.ec2.model.BlockDeviceMapping; import com.amazonaws.services.ec2.model.InstanceNetworkInterface; import com.amazonaws.services.ec2.model.InstancePrivateIpAddress; import com.amazonaws.services.ec2.model.Tag; import com.clouck.comparator.CompareResult; import com.clouck.model.aws.AbstractResource; import com.clouck.model.aws.ec2.Ec2Instance; import com.clouck.service.CompareResourceResult; import com.clouck.validator.Ec2ResourceValidator; @Component public class ResourceUtil { private static final Logger log = LoggerFactory.getLogger(ResourceUtil.class); @Autowired private Ec2ResourceValidator validator; public <R extends AbstractResource<?>> Map<String, R> generateKeyMap(List<R> resources) { Map<String, R> result = new HashMap<>(); for (R resource : resources) { result.put(resource.getUniqueId(), resource); } return result; } public <L> Map<Integer, L> generateHashCodeKeyMap(List<L> list) { Map<Integer, L> result = new HashMap<>(); for (L object : list) { result.put(object.hashCode(), object); } return result; } public static Map<String, Tag> generateTagKeyMap(List<Tag> list) { Map<String, Tag> result = new HashMap<>(); for (Tag tag : list) { result.put(tag.getKey(), tag); } return result; } public Map<String, InstanceNetworkInterface> generateNetworkInterfaceId(List<InstanceNetworkInterface> networkInterfaces) { Map<String, InstanceNetworkInterface> result = new HashMap<>(); for (InstanceNetworkInterface networkInterface : networkInterfaces) { result.put(networkInterface.getNetworkInterfaceId(), networkInterface); } return result; } public Map<String, InstancePrivateIpAddress> generatePrivateIpAddress(List<InstancePrivateIpAddress> privateIpAddresses) { Map<String, InstancePrivateIpAddress> result = new HashMap<>(); for (InstancePrivateIpAddress privateIpAddress : privateIpAddresses) { result.put(privateIpAddress.getPrivateIpAddress(), privateIpAddress); } return result; } public Map<String, BlockDeviceMapping> generateBlockDeviceMapping(List<BlockDeviceMapping> blockDeviceMappings) { Map<String, BlockDeviceMapping> result = new HashMap<>(); for (BlockDeviceMapping blockDeviceMapping : blockDeviceMappings) { result.put(blockDeviceMapping.getDeviceName(), blockDeviceMapping); } return result; } public CompareResult<BlockDeviceMapping> compareBlockDeviceMappings(List<BlockDeviceMapping> oldBlockDeviceMappings, List<BlockDeviceMapping> newBlockDeviceMappings) { Validate.noNullElements(new Object[]{oldBlockDeviceMappings, newBlockDeviceMappings}); CompareResult<BlockDeviceMapping> result = new CompareResult<>(); Map<String, BlockDeviceMapping> oldBlockDeviceMappingMap = generateBlockDeviceMapping(oldBlockDeviceMappings); Map<String, BlockDeviceMapping> newBlockDeviceMappingMap = generateBlockDeviceMapping(newBlockDeviceMappings); for (String newKey : newBlockDeviceMappingMap.keySet()) { BlockDeviceMapping newBDM = newBlockDeviceMappingMap.get(newKey); BlockDeviceMapping oldBDM = oldBlockDeviceMappingMap.get(newKey); if (oldBDM != null) { if (!oldBDM.equals(newBDM)) { result.getUpdate().add(Pair.of(oldBDM, newBDM)); } } else { result.getAdd().add(newBDM); } oldBlockDeviceMappingMap.remove(newKey); } for (String oldKey : oldBlockDeviceMappingMap.keySet()) { BlockDeviceMapping oldBlockDeviceMapping = oldBlockDeviceMappingMap.get(oldKey); result.getDelete().add(oldBlockDeviceMapping); } return result; } public CompareResult<InstancePrivateIpAddress> comparePrivateIpAddresses(List<InstancePrivateIpAddress> oldPrivateIpAddresses, List<InstancePrivateIpAddress> newPrivateIpAddresses) { Validate.noNullElements(new Object[]{oldPrivateIpAddresses, newPrivateIpAddresses}); CompareResult<InstancePrivateIpAddress> result = new CompareResult<>(); Map<String, InstancePrivateIpAddress> oldPrivateIpAddressMap = generatePrivateIpAddress(oldPrivateIpAddresses); Map<String, InstancePrivateIpAddress> newPrivateIpAddressMap = generatePrivateIpAddress(newPrivateIpAddresses); for (String newKey : newPrivateIpAddressMap.keySet()) { InstancePrivateIpAddress newIPI = newPrivateIpAddressMap.get(newKey); InstancePrivateIpAddress oldIPI = oldPrivateIpAddressMap.get(newKey); if (oldIPI != null) { if (!oldIPI.equals(newIPI)) { result.getUpdate().add(Pair.of(oldIPI, newIPI)); } } else { result.getAdd().add(newIPI); } oldPrivateIpAddressMap.remove(newKey); } for (String oldKey : oldPrivateIpAddressMap.keySet()) { InstancePrivateIpAddress oldPrivateIpAddress = oldPrivateIpAddressMap.get(oldKey); result.getDelete().add(oldPrivateIpAddress); } return result; } public CompareResult<InstanceNetworkInterface> compareNetworkInterfaces(List<InstanceNetworkInterface> oldNetworkInterfaces, List<InstanceNetworkInterface> newNetworkInterfaces) { Validate.noNullElements(new Object[]{oldNetworkInterfaces, newNetworkInterfaces}); CompareResult<InstanceNetworkInterface> result = new CompareResult<>(); Map<String, InstanceNetworkInterface> oldNetworkInterfaceIdMap = generateNetworkInterfaceId(oldNetworkInterfaces); Map<String, InstanceNetworkInterface> newNetworkInterfaceIdMap = generateNetworkInterfaceId(newNetworkInterfaces); for (String newKey : newNetworkInterfaceIdMap.keySet()) { InstanceNetworkInterface newINI = newNetworkInterfaceIdMap.get(newKey); InstanceNetworkInterface oldINI = oldNetworkInterfaceIdMap.get(newKey); if (oldINI != null) { Ec2Instance.sortInstanceNetworkInterface(oldINI); Ec2Instance.sortInstanceNetworkInterface(newINI); if (!oldINI.equals(newINI)) { result.getUpdate().add(Pair.of(oldINI, newINI)); } } else { result.getAdd().add(newINI); } oldNetworkInterfaceIdMap.remove(newKey); } for (String oldKey : oldNetworkInterfaceIdMap.keySet()) { InstanceNetworkInterface oldInstanceNetworkInterface = oldNetworkInterfaceIdMap.get(oldKey); result.getDelete().add(oldInstanceNetworkInterface); } return result; } public <R> CompareResult<R> compare(List<R> oldList, List<R> newList) { Validate.noNullElements(new Object[]{oldList, newList}); CompareResult<R> result = new CompareResult<>(); Map<Integer, R> oldListKeyMap = generateHashCodeKeyMap(oldList); Map<Integer, R> newListKeyMap = generateHashCodeKeyMap(newList); for (Integer newKey : newListKeyMap.keySet()) { R newObject = newListKeyMap.get(newKey); R oldObject = oldListKeyMap.get(newKey); if (oldObject == null) { result.getAdd().add(newObject); } oldListKeyMap.remove(newKey); } for (Integer oldKey : oldListKeyMap.keySet()) { R oldObject = oldListKeyMap.get(oldKey); result.getDelete().add(oldObject); } return result; } public CompareResult<Tag> compareTags(List<Tag> oldTags, List<Tag> newTags) { Validate.noNullElements(new Object[]{oldTags, newTags}); CompareResult<Tag> result = new CompareResult<>(); Map<String, Tag> oldTagKeyMap = ResourceUtil.generateTagKeyMap(oldTags); Map<String, Tag> newTagKeyMap = ResourceUtil.generateTagKeyMap(newTags); for (String newKey : newTagKeyMap.keySet()) { Tag newTag = newTagKeyMap.get(newKey); Tag oldTag = oldTagKeyMap.get(newKey); if (oldTag != null) { if (!oldTag.equals(newTag)) { result.getUpdate().add(Pair.of(oldTag, newTag)); } } else { result.getAdd().add(newTag); } oldTagKeyMap.remove(newKey); } for (String oldKey : oldTagKeyMap.keySet()) { Tag oldTag = oldTagKeyMap.get(oldKey); result.getDelete().add(oldTag); } return result; } public CompareResourceResult<AbstractResource<?>> compareResources(List<AbstractResource<?>> oldResources, List<AbstractResource<?>> newResources) { validator.validate(oldResources, newResources); CompareResourceResult<AbstractResource<?>> result = new CompareResourceResult<>(); Map<String, AbstractResource<?>> oldKeyMap = generateKeyMap(oldResources); Map<String, AbstractResource<?>> newKeyMap = generateKeyMap(newResources); for (String newUniqueId : newKeyMap.keySet()) { AbstractResource<?> newResource = newKeyMap.get(newUniqueId); AbstractResource<?> oldResource = oldKeyMap.get(newUniqueId); if (oldResource != null) { log.debug("unique id {} found, check changes", newUniqueId); if (!oldResource.equals(newResource)) { log.debug("unique id {} changed, add it", newUniqueId); result.getAddedResources().add(newResource); } else { log.debug("unique id {} unchanged, ignore it", newUniqueId); result.getUnchangedResourceIds().add(oldResource.getId()); } } else { log.debug("unique id {} not found, add it", newUniqueId); result.getAddedResources().add(newResource); } oldKeyMap.remove(newUniqueId); } for (AbstractResource<?> deletedResource : oldKeyMap.values()) { log.debug("unique id {} not exist, delete it", deletedResource.getUniqueId()); result.getDeletedResourceIds().add(deletedResource.getId()); } return result; } public static boolean notEqual(Object o1, Object o2) { return !Objects.equals(o1, o2); } @SuppressWarnings({ "unchecked", "rawtypes" }) public static boolean notEqualCollection(Collection c1, Collection c2) { return !c1.containsAll(c2) || !c2.containsAll(c1); } @SuppressWarnings({ "rawtypes", "unchecked" }) public static boolean equalCollection(Collection c1, Collection c2) { return c1.containsAll(c2) && c2.containsAll(c1); } //TODO: in eventserviceimple, generate events using compare as well. }