prompto.aws.EC2 Maven / Gradle / Ivy
package prompto.aws;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;
import prompto.intrinsic.PromptoDocument;
import prompto.intrinsic.PromptoList;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.Ec2ClientBuilder;
import software.amazon.awssdk.services.ec2.model.AllocateAddressResponse;
import software.amazon.awssdk.services.ec2.model.AssociateAddressRequest;
import software.amazon.awssdk.services.ec2.model.AssociateAddressResponse;
import software.amazon.awssdk.services.ec2.model.CopyImageRequest;
import software.amazon.awssdk.services.ec2.model.CopyImageResponse;
import software.amazon.awssdk.services.ec2.model.CreateImageRequest;
import software.amazon.awssdk.services.ec2.model.CreateImageResponse;
import software.amazon.awssdk.services.ec2.model.CreateTagsRequest;
import software.amazon.awssdk.services.ec2.model.DescribeAddressesRequest;
import software.amazon.awssdk.services.ec2.model.DescribeAddressesResponse;
import software.amazon.awssdk.services.ec2.model.DescribeAvailabilityZonesResponse;
import software.amazon.awssdk.services.ec2.model.DescribeImagesRequest;
import software.amazon.awssdk.services.ec2.model.DescribeImagesResponse;
import software.amazon.awssdk.services.ec2.model.DescribeInstanceStatusRequest;
import software.amazon.awssdk.services.ec2.model.DescribeInstanceStatusResponse;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse;
import software.amazon.awssdk.services.ec2.model.DescribeSubnetsResponse;
import software.amazon.awssdk.services.ec2.model.DisassociateAddressRequest;
import software.amazon.awssdk.services.ec2.model.EbsInstanceBlockDeviceSpecification;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
import software.amazon.awssdk.services.ec2.model.Filter;
import software.amazon.awssdk.services.ec2.model.IamInstanceProfileSpecification;
import software.amazon.awssdk.services.ec2.model.ImageState;
import software.amazon.awssdk.services.ec2.model.InstanceBlockDeviceMappingSpecification;
import software.amazon.awssdk.services.ec2.model.InstanceState;
import software.amazon.awssdk.services.ec2.model.LaunchPermission;
import software.amazon.awssdk.services.ec2.model.LaunchPermissionModifications;
import software.amazon.awssdk.services.ec2.model.ModifyImageAttributeRequest;
import software.amazon.awssdk.services.ec2.model.ModifyInstanceAttributeRequest;
import software.amazon.awssdk.services.ec2.model.PermissionGroup;
import software.amazon.awssdk.services.ec2.model.ReleaseAddressRequest;
import software.amazon.awssdk.services.ec2.model.RunInstancesRequest;
import software.amazon.awssdk.services.ec2.model.RunInstancesResponse;
import software.amazon.awssdk.services.ec2.model.StartInstancesRequest;
import software.amazon.awssdk.services.ec2.model.StopInstancesRequest;
import software.amazon.awssdk.services.ec2.model.Tag;
import software.amazon.awssdk.services.ec2.model.TerminateInstancesRequest;
public class EC2 {
@SuppressWarnings("resource")
public static EC2 newInstance(String awsRegion, String login, String password) {
Ec2ClientBuilder builder = Ec2Client.builder()
.region(Region.of(awsRegion));
if(login!=null && password!=null) {
AwsCredentials credentials = AwsBasicCredentials.create(login, password);
builder = builder.credentialsProvider(StaticCredentialsProvider.create(credentials));
}
return new EC2(builder.build());
}
Ec2Client ec2;
public EC2(Ec2Client ec2) {
this.ec2 = ec2;
}
@Override
public void finalize() {
this.ec2.close();
}
public String runInstance(String imageId, String instanceType, String keyName, String iamRoleName, List securityGroups, String userData) {
try {
RunInstancesRequest.Builder builder = RunInstancesRequest.builder()
.imageId(imageId)
.instanceType(instanceType)
.minCount(1)
.maxCount(1)
.keyName(keyName);
if(userData!=null)
builder = builder.userData(Base64.getEncoder().encodeToString(userData.getBytes()));
if(securityGroups!=null && !securityGroups.isEmpty())
builder = builder.securityGroups(securityGroups);
if(iamRoleName!=null && !iamRoleName.isEmpty()) {
IamInstanceProfileSpecification iamProfile = null;
if(iamRoleName!=null && !iamRoleName.isEmpty())
iamProfile = IamInstanceProfileSpecification.builder().name(iamRoleName).build();
builder = builder.iamInstanceProfile(iamProfile);
}
RunInstancesResponse runResult = ec2.runInstances(builder.build());
return runResult.instances().get(0).instanceId();
} catch(Ec2Exception e) {
throw e;
}
}
public void waitForInstanceState(String instanceId, String stateName, int timeOutInSecs) {
DescribeInstanceStatusRequest statusRequest = DescribeInstanceStatusRequest.builder()
.instanceIds(instanceId)
.includeAllInstances(true)
.build();
InstanceState state = InstanceState.builder().name(stateName).build();
InstanceState read = null;
long start = System.currentTimeMillis();
do {
try {
DescribeInstanceStatusResponse describeResult = ec2.describeInstanceStatus(statusRequest);
read = describeResult.instanceStatuses().get(0).instanceState();
if(read != state)
Utils.unsafeSleep(1000);
} catch(Ec2Exception e) {
if("InvalidInstanceID.NotFound".equals(e.awsErrorDetails().errorCode()))
read = InstanceState.builder().name("terminated").build();
else
throw e;
}
} while(read != state && (System.currentTimeMillis() - start < timeOutInSecs*1000));
}
public void setInstanceName(String instanceId, String name) {
// this is typically called immediately after creating an instance
// however, the instance may not exist yet (can take a few secs)
waitForInstanceState(instanceId, "pending", 10);
CreateTagsRequest.Builder tagsRequestBuilder = CreateTagsRequest.builder()
.resources(instanceId)
.tags(Tag.builder().key("Name").value(name).build());
ec2.createTags(tagsRequestBuilder.build());
}
public void setInstanceAutoDeleteVolume(String instanceId, String deviceName, boolean autoDelete) {
ModifyInstanceAttributeRequest modifyRequest = ModifyInstanceAttributeRequest.builder()
.blockDeviceMappings(InstanceBlockDeviceMappingSpecification.builder()
.deviceName(deviceName)
.ebs(EbsInstanceBlockDeviceSpecification.builder()
.deleteOnTermination(autoDelete)
.build())
.build())
.build();
ec2.modifyInstanceAttribute(modifyRequest);
}
public void startInstance(String instanceId) {
StartInstancesRequest startRequest = StartInstancesRequest.builder()
.instanceIds(instanceId).build();
ec2.startInstances(startRequest);
}
public void stopInstance(String instanceId) {
StopInstancesRequest stopRequest = StopInstancesRequest.builder()
.instanceIds(instanceId).build();
ec2.stopInstances(stopRequest);
}
public void dropInstance(String instanceId) {
TerminateInstancesRequest dropRequest = TerminateInstancesRequest.builder()
.instanceIds(instanceId).build();
ec2.terminateInstances(dropRequest);
}
public PromptoList> listInstances() {
PromptoList> list = new PromptoList>(true);
DescribeInstancesResponse result = ec2.describeInstances();
result.reservations().forEach((r)->{
r.instances().forEach((i)->{
PromptoDocument doc = Converter.convertPojo(i);
promoteNameTag(i.tags(), doc);
list.add(doc);
});
});
return list;
}
public PromptoList> listIpAddresses() {
PromptoList> list = new PromptoList>(true);
DescribeAddressesResponse result = ec2.describeAddresses();
result.addresses().forEach((a)->{
PromptoDocument doc = Converter.convertPojo(a);
promoteNameTag(a.tags(), doc);
list.add(doc);
});
return list;
}
public String getAddressIdForIpAddress(String ipAddress) {
DescribeAddressesRequest req = DescribeAddressesRequest.builder()
.publicIps(ipAddress)
.build();
try {
DescribeAddressesResponse res = ec2.describeAddresses(req);
if(res.addresses().isEmpty())
return null;
else
return res.addresses().get(0).allocationId();
} catch (Ec2Exception e) {
if("InvalidAddress.NotFound".equals(e.awsErrorDetails().errorCode()))
return null;
throw e;
}
}
public PromptoDocument createIpAddress() {
AllocateAddressResponse newResult = ec2.allocateAddress();
PromptoDocument doc = new PromptoDocument<>();
doc.put("allocationId", newResult.allocationId());
doc.put("publicIp", newResult.publicIp());
doc.put("domain", newResult.domain());
return doc;
}
public void setIpAddressName(String addressId, String name) {
CreateTagsRequest tagsRequest = CreateTagsRequest.builder()
.resources(addressId)
.tags(Tag.builder().key("Name").value(name).build())
.build();
ec2.createTags(tagsRequest);
}
public String associateIPAddress(String instanceId, String addressId) {
AssociateAddressRequest assocRequest = AssociateAddressRequest.builder()
.allocationId(addressId)
.instanceId(instanceId)
.build();
AssociateAddressResponse assocResult = ec2.associateAddress(assocRequest);
return assocResult.associationId();
}
public void dissociateIPAddress(String associationId) {
DisassociateAddressRequest dissocRequest = DisassociateAddressRequest.builder()
.associationId(associationId)
.build();
ec2.disassociateAddress(dissocRequest);
}
public void dropIPAddress(String addressId) {
ReleaseAddressRequest dropRequest = ReleaseAddressRequest.builder()
.allocationId(addressId)
.build();
ec2.releaseAddress(dropRequest);
}
public PromptoList> listOwnedAMIs() {
PromptoList> list = new PromptoList>(true);
DescribeImagesRequest request = DescribeImagesRequest.builder()
.owners("self")
.build();
DescribeImagesResponse result = ec2.describeImages(request);
result.images().forEach(i->{
PromptoDocument doc = Converter.convertPojo(i);
promoteNameTag(i.tags(), doc);
list.add(doc);
});
return list;
}
public PromptoList> listAMIsWithOwnerAndName(String owner, String name) {
PromptoList> list = new PromptoList>(true);
DescribeImagesRequest.Builder builder = DescribeImagesRequest.builder();
if(owner!=null || name!=null) {
List filters = new ArrayList<>();
if(owner!=null)
filters.add(Filter.builder().name("owner-id").values(owner).build());
if(name!=null)
filters.add(Filter.builder().name("name").values(name).build());
builder = builder.filters(filters);
}
DescribeImagesResponse result = ec2.describeImages(builder.build());
result.images().forEach((i)->{
PromptoDocument doc = Converter.convertPojo(i);
promoteNameTag(i.tags(), doc);
list.add(doc);
});
return list;
}
public String createAMI(String instanceId, String name, boolean waitForAvailability) {
String imageId = createAMI(instanceId, name);
setAMINameTag(imageId, name);
if(waitForAvailability)
waitForAMIState(imageId, ImageState.AVAILABLE);
return imageId;
}
public String copyAMI(String srcImageId, String srcRegion, String name, boolean waitForAvailability) {
CopyImageRequest request = CopyImageRequest.builder()
.sourceImageId(srcImageId)
.sourceRegion(srcRegion)
.name(name)
.description("Copied from " + srcImageId + " in " + srcRegion)
.build();
CopyImageResponse result = ec2.copyImage(request);
String dstImageId = result.imageId();
setAMINameTag(dstImageId, name);
if(waitForAvailability)
waitForAMIState(dstImageId, ImageState.AVAILABLE);
return dstImageId;
}
public void setAMIPublic(String imageId) {
LaunchPermissionModifications permissions = LaunchPermissionModifications.builder()
.add(LaunchPermission.builder().group(PermissionGroup.ALL).build())
.build();
ModifyImageAttributeRequest request = ModifyImageAttributeRequest.builder()
.imageId(imageId)
.launchPermission(permissions)
.build();
ec2.modifyImageAttribute(request);
}
public List> listAvailabilityZones() {
DescribeAvailabilityZonesResponse response = ec2.describeAvailabilityZones();
return response.availabilityZones().stream()
.map(Converter::convertPojo)
.collect(Collectors.toList());
}
public List> listSubnets() {
DescribeSubnetsResponse response = ec2.describeSubnets();
return response.subnets().stream()
.map(Converter::convertPojo)
.collect(Collectors.toList());
}
private void waitForAMIState(String imageId, ImageState state) {
DescribeImagesRequest describeRequest = DescribeImagesRequest.builder()
.imageIds(imageId)
.build();
ImageState read = null;
long start = System.currentTimeMillis();
do {
DescribeImagesResponse describeResult = ec2.describeImages(describeRequest);
read = describeResult.images().get(0).state();
if(read != state)
Utils.unsafeSleep(1000);
} while(read != state && (System.currentTimeMillis() - start < 10*60*1000));
}
private void setAMINameTag(String imageId, String name) {
CreateTagsRequest request = CreateTagsRequest.builder()
.resources(imageId)
.tags(Tag.builder().key("Name").value(name).build())
.build();
ec2.createTags(request);
}
private String createAMI(String instanceId, String name) {
CreateImageRequest request = CreateImageRequest.builder()
.instanceId(instanceId)
.name(name)
.build();
CreateImageResponse result = ec2.createImage(request);
return result.imageId();
}
public static void promoteNameTag(List tags, PromptoDocument doc) {
Tag tag = tags.stream()
.filter((t)->"Name".equals(t.key()))
.findFirst()
.orElse(null);
if(tag!=null)
doc.put("Name", tag.value());
else
doc.put("Name", "");
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy