package org.xmlsh.aws;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.xml.stream.XMLStreamException;
import org.xmlsh.aws.util.AWSEC2Command;
import org.xmlsh.core.CoreException;
import org.xmlsh.core.InvalidArgumentException;
import org.xmlsh.core.Options;
import org.xmlsh.core.SafeXMLStreamWriter;
import org.xmlsh.core.UnexpectedException;
import org.xmlsh.core.XValue;
import org.xmlsh.core.io.OutputPort;
import org.xmlsh.util.StringPair;
import org.xmlsh.util.Util;
import com.amazonaws.AmazonClientException;
import com.amazonaws.services.ec2.model.BlockDeviceMapping;
import com.amazonaws.services.ec2.model.InstanceNetworkInterfaceSpecification;
import com.amazonaws.services.ec2.model.Placement;
import com.amazonaws.services.ec2.model.RunInstancesRequest;
import com.amazonaws.services.ec2.model.RunInstancesResult;
import net.sf.saxon.s9api.SaxonApiException;
public class ec2RunInstances extends AWSEC2Command {
/**
* @param args
* @throws IOException
*
* ec2-run-instances ami_id [-n instance_count] [-g group [-g group
* ...]]
* [-k keypair] [-d user_data |-f user_data_file]
* [-instance-type instance_type] [-availability-zone zone] [-kernel
* kernel_id]
* [-ramdisk ramdisk_id] [-block-device-mapping
* block_device_mapping] [-monitor]
* [-disable-api-termination] [-instance-initiated-shutdown-behavior
* behavior]
* [-placement-group placement-group] [-tenancy tenancy] [-subnet
* subnet]
* [-private-ip-address ip_address] [-client-token token]
* [-additional-info info]
* [-dry-run]
*
*/
@Override
public int run(List<XValue> args) throws Exception {
Options opts = getOptions(
"ami=image:,n:,g=group:+,group-id:+,k=key:,d=user-data:,f=user-data-file:,t=instance-type:,availability-zone:,"
+
"kernel:,ramdisk:,block-device-mapping:+,monitor,disable-api-termination,instance-initiated-shutdown-behavior:,"
+
"placement-group:,tenancy:,subnet:,private-ip-address:,client-token:,additional-info:,tag:+,ebs=ebs-optimized",
"dry-run:q,network=network-interface:+");
parseOptions(opts, args);
args = opts.getRemainingArgs();
setSerializeOpts(this.getSerializeOpts(opts));
String image = opts.getOptString("image",
(args.isEmpty() ? null : args.get(0).toString()));
if(image == null) {
usage(null);
return 1;
}
try {
getEC2Client(opts);
} catch (UnexpectedException e) {
usage(e.getLocalizedMessage());
return 1;
}
int ret = runInstance(args.get(0).toString(), opts);
return ret;
}
private int runInstance(String ami_id, Options opts)
throws IOException, XMLStreamException, SaxonApiException, CoreException {
/*
* ec2-run-instances ami_id [-n instance_count] [-g group [-g group ...]]
* [-k keypair] [-d user_data |-f user_data_file]
* [-instance-type instance_type] [-availability-zone zone] [-kernel
* kernel_id]
* [-ramdisk ramdisk_id] [-block-device-mapping block_device_mapping]
* [-monitor]
* [-disable-api-termination] [-instance-initiated-shutdown-behavior
* behavior]
* [-placement-group placement-group] [-tenancy tenancy] [-subnet subnet]
* [-private-ip-address ip_address] [-client-token token]
* [-network-interface ...]
*
*
*/
StringPair minMax = new StringPair(opts.getOptString("n", "1"), '-');
int min = minMax.hasDelim() ? Util.parseInt(minMax.getLeft(), 1)
: Util.parseInt(minMax.getRight(), 1);
int max = minMax.hasDelim() ? Util.parseInt(minMax.getRight(), min) : min;
RunInstancesRequest request = new RunInstancesRequest(ami_id, min, max);
// -g group
List<XValue> xgroups = opts.getOptValues("group");
if(xgroups != null)
request.setSecurityGroups(Util.toStringList(xgroups));
// -g group
List<XValue> xgroupids = opts.getOptValues("group-id");
if(xgroupids != null)
request.setSecurityGroupIds(Util.toStringList(xgroupids));
List<XValue> nifs = opts.getOptValues("network-interface");
if(nifs != null)
request.setNetworkInterfaces(parseNetworkInterfaces(nifs));
// -k keypair
String keypair = opts.getOptString("k", null);
if(keypair != null)
request.setKeyName(keypair);
String userData = getUserData(opts);
if(userData != null)
request.setUserData(userData);
String instanceType = opts.getOptString("instance-type", null);
if(instanceType != null)
request.setInstanceType(instanceType);
Placement placement = getPlacement(opts);
if(placement != null)
request.setPlacement(placement);
String kernel = opts.getOptString("kernel", null);
if(kernel != null)
request.setKernelId(kernel);
String ramdisk = opts.getOptString("ramdisk", null);
if(ramdisk != null)
request.setRamdiskId(ramdisk);
Collection<BlockDeviceMapping> blockDeviceMappings = getBlockDeviceMappings(
opts);
if(blockDeviceMappings != null)
request.setBlockDeviceMappings(blockDeviceMappings);
request.setMonitoring(Boolean.valueOf(opts.hasOpt("monitor")));
request.setDisableApiTermination(
Boolean.valueOf(opts.hasOpt("disable-api-termination")));
String shutdown = opts.getOptString("instance-initiated-shutdown-behavior",
null);
if(shutdown != null)
request.setInstanceInitiatedShutdownBehavior(shutdown);
String subnet = opts.getOptString("subnet", null);
if(subnet != null)
request.setSubnetId(subnet);
String private_ip = opts.getOptString("private-ip-address", null);
if(private_ip != null)
request.setPrivateIpAddress(private_ip);
String client_token = opts.getOptString("client-token", null);
if(client_token != null)
request.setClientToken(client_token);
String info = opts.getOptString("additional-info", null);
if(info != null)
request.setAdditionalInfo(info);
RunInstancesResult result;
if(isDryRun(request))
return dryRun(request);
try {
result = getAWSClient().runInstances(request);
} catch (AmazonClientException e) {
return handleException(e);
}
startResult();
writeResult(result);
endResult();
return 0;
}
private Collection<InstanceNetworkInterfaceSpecification> parseNetworkInterfaces(
List<XValue> nifs) throws InvalidArgumentException, UnexpectedException {
List<InstanceNetworkInterfaceSpecification> nis = new ArrayList<>();
for(XValue xni : nifs) {
if(xni.canConvert(InstanceNetworkInterfaceSpecification.class) < 0)
throw new UnexpectedException(
"InstanceNetworkInterfaceSpecification expected, got: "
+ xni.describe());
nis.add(xni.convert(InstanceNetworkInterfaceSpecification.class));
}
return nis;
}
private void writeResult(RunInstancesResult result)
throws IOException, XMLStreamException, SaxonApiException, CoreException {
OutputPort stdout = this.getStdout();
mWriter = new SafeXMLStreamWriter(
stdout.asXMLStreamWriter(getSerializeOpts()));
startDocument();
startElement(this.getName());
writeReservation(result.getReservation());
endElement();
endDocument();
closeWriter();
stdout.writeSequenceTerminator(getSerializeOpts());
}
private Placement getPlacement(Options opts) {
Placement placement = new Placement();
String availZone = opts.getOptString("availability-zone", null);
if(availZone != null)
placement.setAvailabilityZone(availZone);
String pg = opts.getOptString("placement-group", null);
if(pg != null)
placement.setGroupName(pg);
String tenancy = opts.getOptString("tenancy", null);
if(tenancy != null)
placement.setTenancy(tenancy);
return placement;
}
private String getUserData(Options opts) throws IOException {
String userData = opts.getOptString("d", null);
if(userData != null)
return userData;
XValue file = opts.getOptValue("f");
if(file != null)
return Util.readString(mShell.getFile(file),
getSerializeOpts().getInputTextEncoding());
return null;
}
}