/*******************************************************************************
* Copyright 2012 Urbancode, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.urbancode.terraform.tasks.aws;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.log4j.Logger;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.model.DescribeVpcsRequest;
import com.urbancode.terraform.tasks.aws.helpers.AWSHelper;
import com.urbancode.terraform.tasks.common.exceptions.EnvironmentCreationException;
import com.urbancode.terraform.tasks.common.exceptions.EnvironmentDestructionException;
import com.urbancode.x2o.tasks.Task;
public class VpcTask extends Task {
//**********************************************************************************************
// CLASS
//**********************************************************************************************
final static private Logger log = Logger.getLogger(VpcTask.class);
//**********************************************************************************************
// INSTANCE
//**********************************************************************************************
private AmazonEC2 ec2Client;
private AWSHelper helper;
private ContextAWS context;
private String vpcId;
private String cidr;
private InetGwyTask inetGwy;
private List<SubnetTask> subnets = new ArrayList<SubnetTask>();
private List<VpcSecurityGroupTask> securityGroups = new ArrayList<VpcSecurityGroupTask>();
private List<RouteTableTask> routeTables = new ArrayList<RouteTableTask>();
//----------------------------------------------------------------------------------------------
public VpcTask(ContextAWS context) {
this.context = context;
helper = new AWSHelper();
}
//----------------------------------------------------------------------------------------------
public void setId(String id) {
this.vpcId = id;
}
//----------------------------------------------------------------------------------------------
public void setCidr(String cidr) {
this.cidr = cidr;
}
//----------------------------------------------------------------------------------------------
public String getId() {
return vpcId;
}
//----------------------------------------------------------------------------------------------
public String getCidr() {
return cidr;
}
//----------------------------------------------------------------------------------------------
public List<SubnetTask> getSubnet() {
return Collections.unmodifiableList(subnets);
}
//----------------------------------------------------------------------------------------------
public List<VpcSecurityGroupTask> getSecurityGroupsList() {
return Collections.unmodifiableList(securityGroups);
}
//----------------------------------------------------------------------------------------------
public InetGwyTask getInetGwy() {
return inetGwy;
}
//----------------------------------------------------------------------------------------------
public List<RouteTableTask> getRouteTables() {
return Collections.unmodifiableList(routeTables);
}
//----------------------------------------------------------------------------------------------
public SubnetTask findSubnetForName(String name) {
SubnetTask result = null;
for (SubnetTask subnet : subnets) {
if (subnet.getName().equals(name)) {
result = subnet;
break;
}
}
return result;
}
//----------------------------------------------------------------------------------------------
public VpcSecurityGroupTask findSecurityGroupForName(String name) {
VpcSecurityGroupTask result = null;
for (VpcSecurityGroupTask group : securityGroups) {
if (group.getName().equals(name)) {
result = group;
break;
}
}
return result;
}
//----------------------------------------------------------------------------------------------
public SubnetTask createSubnet() {
SubnetTask subnet = new SubnetTask(context);
subnets.add(subnet);
return subnet;
}
//----------------------------------------------------------------------------------------------
public VpcSecurityGroupTask createVpcSecurityGroup() {
VpcSecurityGroupTask group = new VpcSecurityGroupTask(context);
// set the vpcId on the sec group if possible
if (vpcId != null) {
group.setVpcId(vpcId);
}
securityGroups.add(group);
return group;
}
//----------------------------------------------------------------------------------------------
public InetGwyTask createInetGwy() {
inetGwy = new InetGwyTask(context);
return inetGwy;
}
//----------------------------------------------------------------------------------------------
public RouteTableTask createRouteTable() {
RouteTableTask routeTable = new RouteTableTask(context);
routeTables.add(routeTable);
return routeTable;
}
//----------------------------------------------------------------------------------------------
private void startVpc() {
if (vpcId == null) {
log.info("Starting Vpc...");
setId(helper.createVpc(cidr, ec2Client));
helper.tagInstance(vpcId, "terraform.environment", context.getEnvironment().getName(), ec2Client);
log.info("Vpc created with id: " + vpcId);
}
else {
log.info("Vpc with id " + vpcId + " already exists!");
}
}
//----------------------------------------------------------------------------------------------
private void startInetGwy() {
if (inetGwy != null && inetGwy.getId() == null) {
log.info("Starting Internet Gateway...");
inetGwy.setVpcId(vpcId);
inetGwy.create();
}
else {
if (inetGwy == null) {
log.info("No Internet Gateway specified.");
}
else {
log.info("Internet Gateway with id "+ inetGwy.getId() + " already exists.");
}
}
}
//----------------------------------------------------------------------------------------------
private void startSubnets()
throws Exception {
if (subnets != null || subnets.size() != 0) {
for (SubnetTask subnet : subnets) {
subnet.setVpcId(vpcId);
subnet.create();
}
}
else {
log.info("No subnets specified.");
}
}
//----------------------------------------------------------------------------------------------
private void startRouteTables()
throws Exception {
boolean mainfound = false;
if (routeTables != null) {
// create main table first - since we grab its id by assuming it is the only table
for (RouteTableTask table : routeTables) {
if (table.getDefault()) {
log.debug("Found main table");
String gwyName = "empty";
if (inetGwy != null) {
table.setRouteTarget(inetGwy.getId());
gwyName = inetGwy.getName();
}
table.setVpcId(vpcId);
mainfound = true;
table.create();
log.info("Main route table found with id " + table.getId());
log.info("Default route added :\n" +
"0.0.0.0/0 -> " + gwyName + " (Internet Gateway) ");
break;
}
else {
log.debug("Not main table - skip");
}
}
// see if we found a main table
if (!mainfound) {
log.warn("No main route table found!");
log.warn("the table created will be set as the main table");
log.error("No default route set in VPC " + vpcId +
" - No internet access unless a route was specified manually!");
}
// create all the other tables afterwards
log.debug("Starting secondary route tables");
for (RouteTableTask table : routeTables) {
if (!table.getDefault()) {
log.debug("Found secondary route table");
table.setVpcId(vpcId);
table.create();
}
else {
log.debug("Not a secondary route table - skip");
}
}
}
}
//----------------------------------------------------------------------------------------------
private void startSecurityGroups()
throws Exception {
if (securityGroups != null && !securityGroups.isEmpty()) {
for (VpcSecurityGroupTask group : securityGroups) {
if (group.getId() == null) {
log.info("Starting Security Groups...");
group.setVpcId(vpcId);
group.create();
}
else {
log.info("Security Group with id " + group.getId() + " already exists.");
}
}
}
else {
log.info("No Security Groups specified.");
}
}
//----------------------------------------------------------------------------------------------
public boolean existsInAws() {
// since we have an id, check if Vpc exists in AWS
boolean result = false;
DescribeVpcsRequest vpcReq = new DescribeVpcsRequest().withVpcIds(vpcId);
if (context.fetchEC2Client().describeVpcs(vpcReq) == null) {
log.info("Vpc with id " + vpcId + " does NOT exist in AWS!");
}
else {
result = true;
}
return result;
}
//----------------------------------------------------------------------------------------------
@Override
public void create()
throws EnvironmentCreationException {
if (ec2Client == null) {
ec2Client = context.fetchEC2Client();
}
log.info("Creating Vpc...");
try {
startVpc();
startInetGwy();
startSubnets();
startRouteTables();
startSecurityGroups();
}
catch (Exception e) {
log.error("Did not create VPC completely.", e);
throw new EnvironmentCreationException("Could not completely create Vpc", e);
}
finally {
ec2Client = null;
}
}
//----------------------------------------------------------------------------------------------
@Override
public void destroy()
throws EnvironmentDestructionException {
if (ec2Client == null) {
ec2Client = context.fetchEC2Client();
}
log.info("Destroying Vpc...");
try {
helper.waitForPublicAddresses(ec2Client);
if (getInetGwy() != null) {
getInetGwy().setVpcId(vpcId);
getInetGwy().destroy();
}
helper.waitForPublicAddresses(ec2Client);
// remove route tables
if (getRouteTables() != null && !getRouteTables().isEmpty()) {
for (RouteTableTask table : getRouteTables()) {
table.destroy();
}
}
// remove security Groups
if (securityGroups != null && securityGroups.size() != 0) {
for (VpcSecurityGroupTask group : securityGroups) {
group.destroy();
}
}
// remove Subnets
if (subnets != null && subnets.size() != 0) {
for (SubnetTask subnet : subnets) {
subnet.destroy();
}
}
// delete Vpc
helper.deleteVpc(vpcId, ec2Client);
vpcId = null;
}
catch (Exception e) {
log.error("EXCEPTION CAUGHT WHEN DESTROYING VPC", e);
throw new EnvironmentDestructionException("Could not completely destroy Vpc", e);
}
finally {
ec2Client = null;
}
}
}