diff --git a/bubble-server/pom.xml b/bubble-server/pom.xml index f6214c5b..ff8494e0 100644 --- a/bubble-server/pom.xml +++ b/bubble-server/pom.xml @@ -106,6 +106,12 @@ jetty-proxy ${jetty.version} + + + com.amazonaws + aws-java-sdk-ec2 + 1.11.762 + diff --git a/bubble-server/src/main/java/bubble/cloud/compute/amazonEC2/AmazonEC2Driver.java b/bubble-server/src/main/java/bubble/cloud/compute/amazonEC2/AmazonEC2Driver.java deleted file mode 100644 index d7defcf9..00000000 --- a/bubble-server/src/main/java/bubble/cloud/compute/amazonEC2/AmazonEC2Driver.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Copyright (c) 2020 Bubble, Inc. All rights reserved. - * For personal (non-commercial) use, see license: https://bubblev.com/bubble-license/ - */ -package bubble.cloud.compute.amazonEC2; - -import bubble.cloud.compute.ComputeServiceDriverBase; -import bubble.model.cloud.BubbleNode; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.regions.Regions; -import com.amazonaws.services.ec2.AmazonEC2; -import com.amazonaws.services.ec2.AmazonEC2ClientBuilder; -import com.amazonaws.services.ec2.model.*; -import lombok.extern.slf4j.Slf4j; -import org.cobbzilla.util.http.HttpRequestBean; -import org.cobbzilla.util.http.HttpResponseBean; - -import java.io.IOException; -import java.util.List; - -import static org.cobbzilla.util.string.StringUtil.urlEncode; - -@Slf4j -public class AmazonEC2Driver extends ComputeServiceDriverBase { - - private static final AWSCredentials AWS_CREDENTIALS; - - static { - // Your accesskey and secretkey - AWS_CREDENTIALS = new BasicAWSCredentials( - "Your-ID", - "Your secret-key" - ); - } - - @Override - protected String readSshKeyId(HttpResponseBean keyResponse) { - return null; - } - - @Override - protected HttpRequestBean registerSshKeyRequest(BubbleNode node) { - - return null; - } - - @Override - public List listNodes() throws IOException { - return null; - } - - @Override - public BubbleNode start(BubbleNode node) throws Exception { - AmazonEC2 ec2Client = AmazonEC2ClientBuilder.standard() - .withCredentials(new AWSStaticCredentialsProvider(AWS_CREDENTIALS)) - .withRegion(Regions.US_EAST_1) - .build(); - - ec2Client.importKeyPair(new ImportKeyPairRequest(node.getUuid(), node.getSshKey().getSshPublicKey())); - RunInstancesRequest runInstancesRequest = new RunInstancesRequest().withImageId("ami-0080e4c5bc078760e") - .withInstanceType("t2.micro") // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html - .withMinCount(1) - .withMaxCount(1) - .withKeyName(node.getUuid()) - .withNetworkInterfaces(new InstanceNetworkInterfaceSpecification() - .withAssociatePublicIpAddress(true) - .withDeviceIndex(0) - .withSubnetId("subnet-id") - .withGroups("sg-id")); - - RunInstancesResult runInstancesResult = ec2Client.runInstances(runInstancesRequest); - - Instance instance = runInstancesResult.getReservation().getInstances().get(0); - String instanceId = instance.getInstanceId(); - - // Setting up the tags for the instance - CreateTagsRequest createTagsRequest = new CreateTagsRequest() - .withResources(instance.getInstanceId()) - .withTags(new Tag("Name", "Edurekademo")); - ec2Client.createTags(createTagsRequest); - - // Starting the Instance - StartInstancesRequest startInstancesRequest = new StartInstancesRequest().withInstanceIds(instanceId); - - ec2Client.startInstances(startInstancesRequest); - return null; - } - - @Override - public BubbleNode cleanupStart(BubbleNode node) throws Exception { - return null; - } - - @Override - public BubbleNode stop(BubbleNode node) throws Exception { - return null; - } - - @Override - public BubbleNode status(BubbleNode node) throws Exception { - return null; - } -} diff --git a/bubble-server/src/main/java/bubble/cloud/compute/ec2/AmazonEC2Driver.java b/bubble-server/src/main/java/bubble/cloud/compute/ec2/AmazonEC2Driver.java new file mode 100644 index 00000000..28af8ba4 --- /dev/null +++ b/bubble-server/src/main/java/bubble/cloud/compute/ec2/AmazonEC2Driver.java @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2020 Bubble, Inc. All rights reserved. + * For personal (non-commercial) use, see license: https://bubblev.com/bubble-license/ + */ +package bubble.cloud.compute.ec2; + +import bubble.cloud.compute.ComputeServiceDriverBase; +import bubble.cloud.shared.aws.BubbleAwsCredentialsProvider; +import bubble.model.cloud.BubbleNode; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.regions.Regions; +import com.amazonaws.services.ec2.AmazonEC2; +import com.amazonaws.services.ec2.AmazonEC2ClientBuilder; +import com.amazonaws.services.ec2.model.*; +import com.amazonaws.services.route53.AmazonRoute53; +import com.amazonaws.services.route53.AmazonRoute53ClientBuilder; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.cobbzilla.util.http.HttpRequestBean; +import org.cobbzilla.util.http.HttpResponseBean; + +import java.io.IOException; +import java.util.List; + +import static bubble.model.cloud.BubbleNode.TAG_SSH_KEY_ID; +import static org.cobbzilla.util.daemon.ZillaRuntime.die; +import static org.cobbzilla.util.http.HttpStatusCodes.OK; + +@Slf4j +public class AmazonEC2Driver extends ComputeServiceDriverBase { + + @Getter(lazy=true) private final AWSCredentialsProvider ec2credentials = new BubbleAwsCredentialsProvider(cloud, getCredentials()); + + @Getter(lazy=true) private final AmazonEC2 ec2Client = initEC2Client(); + private AmazonEC2 initEC2Client() { + final Regions region; + final String regionName = config.getRegion(Regions.DEFAULT_REGION.getName()).getName(); + try { + region = Regions.valueOf(regionName); + } catch (Exception e) { + return die("initEC2Client: invalid region: " + regionName); + } + return AmazonEC2ClientBuilder.standard() + .withRegion(region) + .withCredentials(getEc2credentials()) + .build(); + } + + + + @Override public void postSetup() { + + super.postSetup(); + } + + @Override protected String readSshKeyId(HttpResponseBean keyResponse) { + return null; + } + + @Override protected HttpRequestBean registerSshKeyRequest(BubbleNode node) { + final AmazonEC2 ec2Client = getEc2Client(); + ec2Client.importKeyPair(new ImportKeyPairRequest(node.getUuid(), node.getSshKey().getSshPublicKey())); + return null; + } + + @Override public List listNodes() throws IOException { + return null; + } + + @Override public BubbleNode start(BubbleNode node) throws Exception { + + // TODO: imageID, dibnetID, Group + RunInstancesRequest runInstancesRequest = new RunInstancesRequest().withImageId("ami-0080e4c5bc078760e") + .withInstanceType("t2.micro") // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html + .withMinCount(1) + .withMaxCount(1) + .withKeyName(node.getUuid()) + .withNetworkInterfaces(new InstanceNetworkInterfaceSpecification() + .withAssociatePublicIpAddress(true) + .withDeviceIndex(0) + .withSubnetId("subnet-id") + .withGroups("sg-id")); + + final AmazonEC2 ec2Client = getEc2Client(); + RunInstancesResult runInstancesResult = ec2Client.runInstances(runInstancesRequest); + + Instance instance = runInstancesResult.getReservation().getInstances().get(0); + String instanceId = instance.getInstanceId(); + + // TODO: tags + // Setting up the tags for the instance + CreateTagsRequest createTagsRequest = new CreateTagsRequest() + .withResources(instance.getInstanceId()) + .withTags(new Tag("", "")); + ec2Client.createTags(createTagsRequest); + + // Starting the Instance + StartInstancesRequest startInstancesRequest = new StartInstancesRequest().withInstanceIds(instanceId); + + ec2Client.startInstances(startInstancesRequest); + return null; + } + + @Override public BubbleNode cleanupStart(BubbleNode node) throws Exception { + deleteEC2KeyPair(node); + return node; + } + + @Override public BubbleNode stop(BubbleNode node) throws Exception { + //Stop EC2 Instance + //TODO: instanceID + String instanceID = ""; + StopInstancesRequest stopInstancesRequest = new StopInstancesRequest() + .withInstanceIds(instanceID); + + final AmazonEC2 ec2Client = getEc2Client(); + ec2Client.stopInstances(stopInstancesRequest) + .getStoppingInstances() + .get(0) + .getPreviousState() + .getName(); + return node; + } + + @Override public BubbleNode status(BubbleNode node) throws Exception { + return null; + } + + public void deleteEC2KeyPair(BubbleNode node) throws IOException { + if (node.hasTag(TAG_SSH_KEY_ID)) { + DeleteKeyPairRequest request = new DeleteKeyPairRequest() + .withKeyName(node.getUuid()); + + // destroy key, check response + final AmazonEC2 ec2Client = getEc2Client(); + DeleteKeyPairResult response = ec2Client.deleteKeyPair(request); + + if (response.getSdkHttpMetadata().getHttpStatusCode() != OK) { + log.warn("deleteEC2KeyPair: error deleting EC2keyPair, node: "+ node.getUuid()); + } + } + } +} diff --git a/bubble-server/src/test/resources/models/system/cloudService.json b/bubble-server/src/test/resources/models/system/cloudService.json index a6245b5e..670802e8 100644 --- a/bubble-server/src/test/resources/models/system/cloudService.json +++ b/bubble-server/src/test/resources/models/system/cloudService.json @@ -233,6 +233,21 @@ "template": true }, + { + "_subst": true, + "name": "AmazonEC2Driver", + "type": "compute", + "driverClass": "bubble.cloud.compute.ec2.AmazonEC2Driver", + "driverConfig": {}, + "credentials": { + "params": [ + {"name": "AWS_ACCESS_KEY_ID", "value": "{{AWS_ACCESS_KEY_ID}}"}, + {"name": "AWS_SECRET_KEY", "value": "{{AWS_SECRET_KEY}}"} + ] + }, + "template": true + }, + { "_subst": true, "name": "InviteCode", diff --git a/utils/cobbzilla-wizard b/utils/cobbzilla-wizard index 073dbbc3..23e6ab73 160000 --- a/utils/cobbzilla-wizard +++ b/utils/cobbzilla-wizard @@ -1 +1 @@ -Subproject commit 073dbbc3f8401e946b731e2269f6e253b04bee68 +Subproject commit 23e6ab7399be669a1f9bb9abf64186f3d029eda5