private Integer startTunnelSSH(Instance instance) throws InterruptedException { Instance tunnelInstance = runningInstances(tunnelResourceId).get(0); Integer localPort = Double.valueOf(Randoms.number(3000, 10000)).intValue(); CountDownLatch latch = new CountDownLatch(1); Thread tunnelThread = new Thread( () -> { Process process = null; try { Path keyPath = KeyPair.keyFile(tunnelInstance.getKeyName(), env); String userAndHost = "ubuntu@" + hostName(tunnelInstance); String portBinding = Strings.format("{}:{}:22", localPort, instance.getPrivateIpAddress()); List<String> command = tunnelCommand(keyPath, userAndHost, portBinding); logger.info("tunnel command => {}", String.join(" ", command)); process = new ProcessBuilder().command(command).start(); process.getInputStream().read(); // wait until there is output latch.countDown(); process.waitFor(); } catch (InterruptedException | IOException e) { throw new IllegalStateException(e); } finally { if (process != null) process.destroy(); } }); tunnelThread.setDaemon(true); tunnelThread.start(); latch.await(); return localPort; }
@Override public void execute(Context context) throws Exception { RunInstancesRequest request = new RunInstancesRequest() .withKeyName(resource.keyPair.remoteKeyPair.getKeyName()) .withInstanceType(resource.instanceType) .withImageId(resource.ami.imageId()) .withMinCount(addedCount) .withMaxCount(addedCount) .withUserData(Base64.encodeBase64String(Strings.bytes(userData(context.env)))); if (resource.instanceProfile != null) request.withIamInstanceProfile( new IamInstanceProfileSpecification() .withName(resource.instanceProfile.remoteInstanceProfile.getInstanceProfileName())); String sgId = resource.securityGroup.remoteSecurityGroup.getGroupId(); request .getNetworkInterfaces() .add( new InstanceNetworkInterfaceSpecification() .withDeviceIndex(0) .withSubnetId(resource.subnet.firstRemoteSubnet().getSubnetId()) .withGroups(sgId) .withAssociatePublicIpAddress(resource.subnet.type == SubnetType.PUBLIC)); if (resource.ebs.rootVolumeSize != null) { request .getBlockDeviceMappings() .add( new BlockDeviceMapping() .withDeviceName("/dev/sda1") .withEbs(new EbsBlockDevice().withVolumeSize(resource.ebs.rootVolumeSize))); } List<com.amazonaws.services.ec2.model.Instance> remoteInstances = AWS.ec2.runInstances(request, tags(context.env)); resource.remoteInstances.addAll(remoteInstances); for (com.amazonaws.services.ec2.model.Instance remoteInstance : remoteInstances) { String key = String.format("instance/%s/%s", resource.id, remoteInstance.getInstanceId()); StringBuilder builder = new StringBuilder(); builder.append("privateIP=").append(remoteInstance.getPrivateIpAddress()); if (resource.subnet == null || resource.subnet.type == SubnetType.PUBLIC) { builder.append(", publicDNS=").append(remoteInstance.getPublicDnsName()); } context.output(key, builder.toString()); } if (resource.elb != null) { List<String> instanceIds = remoteInstances .stream() .map(com.amazonaws.services.ec2.model.Instance::getInstanceId) .collect(Collectors.toList()); AWS.elb.attachInstances( resource.elb.remoteELB.getLoadBalancerName(), instanceIds, waitUntilInService); } }