package com.clouck.wrapper.aws;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.CreateVolumePermission;
import com.amazonaws.services.ec2.model.DescribeAddressesRequest;
import com.amazonaws.services.ec2.model.DescribeAddressesResult;
import com.amazonaws.services.ec2.model.DescribeDhcpOptionsRequest;
import com.amazonaws.services.ec2.model.DescribeDhcpOptionsResult;
import com.amazonaws.services.ec2.model.DescribeImageAttributeRequest;
import com.amazonaws.services.ec2.model.DescribeImageAttributeResult;
import com.amazonaws.services.ec2.model.DescribeImagesRequest;
import com.amazonaws.services.ec2.model.DescribeImagesResult;
import com.amazonaws.services.ec2.model.DescribeInstanceAttributeRequest;
import com.amazonaws.services.ec2.model.DescribeInstanceAttributeResult;
import com.amazonaws.services.ec2.model.DescribeInstancesRequest;
import com.amazonaws.services.ec2.model.DescribeInstancesResult;
import com.amazonaws.services.ec2.model.DescribeInternetGatewaysRequest;
import com.amazonaws.services.ec2.model.DescribeInternetGatewaysResult;
import com.amazonaws.services.ec2.model.DescribeKeyPairsRequest;
import com.amazonaws.services.ec2.model.DescribeKeyPairsResult;
import com.amazonaws.services.ec2.model.DescribeNetworkAclsRequest;
import com.amazonaws.services.ec2.model.DescribeNetworkAclsResult;
import com.amazonaws.services.ec2.model.DescribeNetworkInterfacesRequest;
import com.amazonaws.services.ec2.model.DescribeNetworkInterfacesResult;
import com.amazonaws.services.ec2.model.DescribePlacementGroupsRequest;
import com.amazonaws.services.ec2.model.DescribePlacementGroupsResult;
import com.amazonaws.services.ec2.model.DescribeRouteTablesRequest;
import com.amazonaws.services.ec2.model.DescribeRouteTablesResult;
import com.amazonaws.services.ec2.model.DescribeSecurityGroupsRequest;
import com.amazonaws.services.ec2.model.DescribeSecurityGroupsResult;
import com.amazonaws.services.ec2.model.DescribeSnapshotAttributeRequest;
import com.amazonaws.services.ec2.model.DescribeSnapshotAttributeResult;
import com.amazonaws.services.ec2.model.DescribeSnapshotsRequest;
import com.amazonaws.services.ec2.model.DescribeSnapshotsResult;
import com.amazonaws.services.ec2.model.DescribeSpotInstanceRequestsRequest;
import com.amazonaws.services.ec2.model.DescribeSpotInstanceRequestsResult;
import com.amazonaws.services.ec2.model.DescribeSubnetsRequest;
import com.amazonaws.services.ec2.model.DescribeSubnetsResult;
import com.amazonaws.services.ec2.model.DescribeVolumeAttributeRequest;
import com.amazonaws.services.ec2.model.DescribeVolumesRequest;
import com.amazonaws.services.ec2.model.DescribeVolumesResult;
import com.amazonaws.services.ec2.model.DescribeVpcsRequest;
import com.amazonaws.services.ec2.model.DescribeVpcsResult;
import com.amazonaws.services.ec2.model.Filter;
import com.amazonaws.services.ec2.model.Image;
import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.ec2.model.LaunchPermission;
import com.amazonaws.services.ec2.model.ProductCode;
import com.amazonaws.services.ec2.model.Reservation;
import com.amazonaws.services.ec2.model.Snapshot;
import com.amazonaws.services.ec2.model.Volume;
import com.clouck.application.Ec2Filter;
import com.clouck.converter.Ec2Converter;
import com.clouck.model.Account;
import com.clouck.model.Region;
import com.clouck.model.aws.AbstractResource;
import com.clouck.model.aws.ec2.Ec2InstanceAttribute;
@Component
public class Ec2WrapperImpl implements Ec2Wrapper {
private static final Logger log = LoggerFactory.getLogger(Ec2WrapperImpl.class);
@Autowired
private Ec2Converter converter;
private AmazonEC2 findClient(Account account, Region region) {
// TODO: need to config client config parameter. ignore it for now.
// TODO: need a cached version based on account and region as key
AWSCredentials credential = new BasicAWSCredentials(account.getAccessKeyId(), account.getSecretAccessKey());
AmazonEC2 ec2 = new AmazonEC2Client(credential);
ec2.setRegion(com.amazonaws.regions.Region.getRegion(region.getRegions()));
return ec2;
}
@Override
public List<AbstractResource<?>> describeSpotInstanceRequests(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeSpotInstanceRequestsRequest req = new DescribeSpotInstanceRequestsRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing spot instance requests for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeSpotInstanceRequestsResult res = ec2.describeSpotInstanceRequests(req);
return converter.toEc2SpotInstanceRequest(res.getSpotInstanceRequests(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describeReservations(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeInstancesRequest req = new DescribeInstancesRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing instances for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeInstancesResult res = ec2.describeInstances(req);
List<Map<String, Ec2InstanceAttribute>> attributes = new ArrayList<>();
for (Reservation r : res.getReservations()) {
Map<String, Ec2InstanceAttribute> attribute = new HashMap<>();
for (Instance i : r.getInstances()) {
Boolean terminationProtection = findTerminationProtection(account, region, i.getInstanceId());
String shutdownBehavior = findShutdownBehavior(account, region, i.getInstanceId());
String userData = findUserData(account, region, i.getInstanceId());
Ec2InstanceAttribute ia = new Ec2InstanceAttribute(terminationProtection, shutdownBehavior, userData);
attribute.put(i.getInstanceId(), ia);
}
attributes.add(attribute);
}
return converter.toEc2Reservations(res.getReservations(), attributes, account.getId(), region, dt);
}
@Override
public Boolean findTerminationProtection(Account account, Region region, String instanceId) {
AmazonEC2 ec2 = findClient(account, region);
DescribeInstanceAttributeRequest req = new DescribeInstanceAttributeRequest();
req.setAttribute("disableApiTermination");
req.setInstanceId(instanceId);
log.debug("start describing instance termination protection for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeInstanceAttributeResult res = ec2.describeInstanceAttribute(req);
return res.getInstanceAttribute().getDisableApiTermination();
}
@Override
public String findShutdownBehavior(Account account, Region region, String instanceId) {
AmazonEC2 ec2 = findClient(account, region);
DescribeInstanceAttributeRequest req = new DescribeInstanceAttributeRequest();
req.setAttribute("instanceInitiatedShutdownBehavior");
req.setInstanceId(instanceId);
log.debug("start describing instance shutdown behavior for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeInstanceAttributeResult res = ec2.describeInstanceAttribute(req);
return res.getInstanceAttribute().getInstanceInitiatedShutdownBehavior();
}
@Override
public String findUserData(Account account, Region region, String instanceId) {
AmazonEC2 ec2 = findClient(account, region);
DescribeInstanceAttributeRequest req = new DescribeInstanceAttributeRequest();
req.setAttribute("userData");
req.setInstanceId(instanceId);
log.debug("start describing instance user data for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeInstanceAttributeResult res = ec2.describeInstanceAttribute(req);
return res.getInstanceAttribute().getUserData();
}
@Override
public List<AbstractResource<?>> describeSecurityGroups(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeSecurityGroupsRequest req = new DescribeSecurityGroupsRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing security groups for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeSecurityGroupsResult res = ec2.describeSecurityGroups(req);
return converter.toEc2SecurityGroups(res.getSecurityGroups(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describeAMIs(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeImagesRequest req = new DescribeImagesRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing amis for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeImagesResult res = ec2.describeImages(req);
List<List<LaunchPermission>> imageLaunchPermissions = new ArrayList<>();
for (Image image : res.getImages()) {
imageLaunchPermissions.add(findImageLaunchPermissions(account, region, image.getImageId()));
}
return converter.toEc2AMIs(res.getImages(), imageLaunchPermissions, account.getId(), region, dt);
}
@Override
public List<LaunchPermission> findImageLaunchPermissions(Account account, Region region, String imageId) {
AmazonEC2 ec2 = findClient(account, region);
DescribeImageAttributeRequest req = new DescribeImageAttributeRequest();
req.setAttribute("launchPermission");
req.setImageId(imageId);
log.debug("start describing image launch permission for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeImageAttributeResult res = ec2.describeImageAttribute(req);
List<LaunchPermission> launchPermissions = res.getImageAttribute().getLaunchPermissions();
return removeGroup(launchPermissions);
}
private List<LaunchPermission> removeGroup(List<LaunchPermission> permissions) {
List<LaunchPermission> result = new ArrayList<>();
for (LaunchPermission lp : permissions) {
if (lp.getGroup() == null) {
result.add(lp);
}
}
return result;
}
@Override
public List<AbstractResource<?>> describeVolumes(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeVolumesRequest req = new DescribeVolumesRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing volumes for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeVolumesResult res = ec2.describeVolumes(req);
List<Boolean> autoEnableIOs = new ArrayList<>();
List<List<ProductCode>> productCodes = new ArrayList<>();
for (Volume volume : res.getVolumes()) {
autoEnableIOs.add(findAutoEnableIO(account, region, volume.getVolumeId()));
productCodes.add(findProductCodes(account, region, volume.getVolumeId()));
}
return converter.toEc2Volumes(res.getVolumes(), autoEnableIOs, productCodes, account.getId(), region, dt);
}
@Override
public Boolean findAutoEnableIO(Account account, Region region, String volumeId) {
AmazonEC2 ec2 = findClient(account, region);
DescribeVolumeAttributeRequest req = new DescribeVolumeAttributeRequest();
req.setVolumeId(volumeId);
req.setAttribute("autoEnableIO");
log.debug("start describing volume attribute auto enable io for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
return ec2.describeVolumeAttribute(req).getAutoEnableIO();
}
@Override
public List<ProductCode> findProductCodes(Account account, Region region, String volumeId) {
AmazonEC2 ec2 = findClient(account, region);
DescribeVolumeAttributeRequest req = new DescribeVolumeAttributeRequest();
req.setVolumeId(volumeId);
req.setAttribute("productCodes");
log.debug("start describing volume attribute product codes for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
return ec2.describeVolumeAttribute(req).getProductCodes();
}
// public List<LaunchPermission> findxxxs(Account account, Region region, String volumeId) {
// AmazonEC2 ec2 = findClient(account, region);
//
// DescribeVolumeStatusRequest req = new DescribeVolumeStatusRequest();
// req.setVolumeIds(Lists.newArrayList(volumeId));
//
// log.debug("start describing image launch permission for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
// DescribeVolumeStatusResult res = ec2.describeVolumeStatus(req);
//
// List<VolumeStatusItem> volumeStatuses = res.getVolumeStatuses();
// return removeGroup(launchPermissions);
// }
@Override
public List<AbstractResource<?>> describeSnapshots(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeSnapshotsRequest req = new DescribeSnapshotsRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing snapshots for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeSnapshotsResult res = ec2.describeSnapshots(req);
List<List<CreateVolumePermission>> createVolumePermissions = new ArrayList<>();
List<List<ProductCode>> productCodes = new ArrayList<>();
for (Snapshot snapShot : res.getSnapshots()) {
productCodes.add(findSnapshotProductCodes(account, region, snapShot.getSnapshotId()));
createVolumePermissions.add(findCreateVolumePermissions(account, region, snapShot.getSnapshotId()));
}
return converter.toEc2Snapshots(res.getSnapshots(), createVolumePermissions, productCodes, account.getId(), region, dt);
}
@Override
public List<CreateVolumePermission> findCreateVolumePermissions(Account account, Region region, String snapshotId) {
AmazonEC2 ec2 = findClient(account, region);
DescribeSnapshotAttributeRequest req = new DescribeSnapshotAttributeRequest();
req.setAttribute("createVolumePermission");
req.setSnapshotId(snapshotId);
log.debug("start describing snapshot create volume permission for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeSnapshotAttributeResult res = ec2.describeSnapshotAttribute(req);
return res.getCreateVolumePermissions();
}
@Override
public List<ProductCode> findSnapshotProductCodes(Account account, Region region, String snapshotId) {
AmazonEC2 ec2 = findClient(account, region);
DescribeSnapshotAttributeRequest req = new DescribeSnapshotAttributeRequest();
req.setAttribute("productCodes");
req.setSnapshotId(snapshotId);
log.debug("start describing snapshot productCodes for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeSnapshotAttributeResult res = ec2.describeSnapshotAttribute(req);
return res.getProductCodes();
}
@Override
public List<AbstractResource<?>> describeKeyPairs(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeKeyPairsRequest req = new DescribeKeyPairsRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing key pairs for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeKeyPairsResult res = ec2.describeKeyPairs(req);
return converter.toEc2KeyPairs(res.getKeyPairs(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describeElasticIPs(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeAddressesRequest req = new DescribeAddressesRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing elastic ips for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeAddressesResult res = ec2.describeAddresses(req);
return converter.toEc2ElasticIPs(res.getAddresses(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describePlacementGroups(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribePlacementGroupsRequest req = new DescribePlacementGroupsRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing placement groups for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribePlacementGroupsResult res = ec2.describePlacementGroups(req);
return converter.toEc2PlacementGroups(res.getPlacementGroups(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describeNetworkInterfaces(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeNetworkInterfacesRequest req = new DescribeNetworkInterfacesRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing network interfaces for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeNetworkInterfacesResult res = ec2.describeNetworkInterfaces(req);
return converter.toEc2NetworkInterfaces(res.getNetworkInterfaces(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describeVpcs(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeVpcsRequest req = new DescribeVpcsRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing vpcs for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeVpcsResult res = ec2.describeVpcs(req);
return converter.toVpcVpcs(res.getVpcs(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describeSubnets(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeSubnetsRequest req = new DescribeSubnetsRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing subnets for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeSubnetsResult res = ec2.describeSubnets(req);
return converter.toVpcSubnets(res.getSubnets(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describeRouteTables(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeRouteTablesRequest req = new DescribeRouteTablesRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing route tables for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeRouteTablesResult res = ec2.describeRouteTables(req);
return converter.toVpcRouteTables(res.getRouteTables(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describeInternetGateways(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeInternetGatewaysRequest req = new DescribeInternetGatewaysRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing internet gateways for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeInternetGatewaysResult res = ec2.describeInternetGateways(req);
return converter.toVpcInternetGateways(res.getInternetGateways(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describeDhcpOptions(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeDhcpOptionsRequest req = new DescribeDhcpOptionsRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing dhcp options for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeDhcpOptionsResult res = ec2.describeDhcpOptions(req);
return converter.toVpcDhcpOptions(res.getDhcpOptions(), account.getId(), region, dt);
}
@Override
public List<AbstractResource<?>> describeNetworkAcls(Account account, Region region, DateTime dt, Ec2Filter... filters) {
AmazonEC2 ec2 = findClient(account, region);
DescribeNetworkAclsRequest req = new DescribeNetworkAclsRequest();
for (Ec2Filter filter : filters) {
Filter f = new Filter().withName(filter.getName()).withValues(filter.getValues());
req.withFilters(f);
}
log.debug("start describing network acls for account:{} in region:{} via api", account.getId() + "=>" + account.getName(), region);
DescribeNetworkAclsResult res = ec2.describeNetworkAcls(req);
return converter.toVpcNetworkAcls(res.getNetworkAcls(), account.getId(), region, dt);
}
}