package com.sequenceiq.it.cloudbreak;
import static com.amazonaws.services.cloudformation.model.StackStatus.CREATE_COMPLETE;
import static com.amazonaws.services.cloudformation.model.StackStatus.CREATE_FAILED;
import static com.amazonaws.services.cloudformation.model.StackStatus.ROLLBACK_COMPLETE;
import static com.amazonaws.services.cloudformation.model.StackStatus.ROLLBACK_FAILED;
import static com.amazonaws.services.cloudformation.model.StackStatus.ROLLBACK_IN_PROGRESS;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import com.amazonaws.regions.RegionUtils;
import com.amazonaws.services.cloudformation.AmazonCloudFormationClient;
import com.amazonaws.services.cloudformation.model.CreateStackRequest;
import com.amazonaws.services.cloudformation.model.DescribeStacksRequest;
import com.amazonaws.services.cloudformation.model.Output;
import com.amazonaws.services.cloudformation.model.Parameter;
import com.amazonaws.services.cloudformation.model.Stack;
import com.amazonaws.services.cloudformation.model.StackStatus;
import com.sequenceiq.cloudbreak.api.model.NetworkRequest;
public class AwsCreateVpcNetworkTest extends AbstractCloudbreakIntegrationTest {
private static final List<StackStatus> FAILED_STATUSES = Arrays.asList(CREATE_FAILED, ROLLBACK_IN_PROGRESS, ROLLBACK_FAILED, ROLLBACK_COMPLETE);
private static final Logger LOGGER = LoggerFactory.getLogger(AwsCreateVpcNetworkTest.class);
private static final int MAX_TRY = 30;
@Test
@Parameters({ "networkName", "description", "publicInAccount", "regionName", "vpcStackName", "vpcName", "existingSubnet" })
public void createNetwork(String networkName, @Optional("") String description, @Optional("false") boolean publicInAccount,
String regionName, @Optional("it-vpc-stack") String vpcStackName, @Optional("it-vpc") String vpcName, boolean existingSubnet) {
AmazonCloudFormationClient client = new AmazonCloudFormationClient();
client.setRegion(RegionUtils.getRegion(regionName));
Map<String, Object> networkMap = new HashMap<>();
String vpcCreationJson = existingSubnet ? "public_vpc_with_subnet.json" : "public_vpc_wihout_subnet.json";
try (InputStream vpcJsonInputStream = getClass().getResourceAsStream("/cloudformation/" + vpcCreationJson)) {
String vpcCFTemplateString = IOUtils.toString(vpcJsonInputStream);
CreateStackRequest stackRequest = createStackRequest(vpcStackName, vpcName, vpcCFTemplateString);
client.createStack(stackRequest);
List<Output> outputForRequest = getOutputForRequest(vpcStackName, client);
if (existingSubnet) {
networkMap.put("vpcId", outputForRequest.get(0).getOutputValue());
networkMap.put("subnetId", outputForRequest.get(1).getOutputValue());
} else {
networkMap.put("vpcId", outputForRequest.get(1).getOutputValue());
networkMap.put("internetGatewayId", outputForRequest.get(0).getOutputValue());
}
} catch (IOException e) {
LOGGER.error("can't read vpc cloudformation template file");
throw new RuntimeException(e);
}
NetworkRequest networkRequest = new NetworkRequest();
networkRequest.setName(networkName);
networkRequest.setDescription(description);
networkRequest.setParameters(networkMap);
if (!existingSubnet) {
networkRequest.setSubnetCIDR("10.0.0.0/24");
}
networkRequest.setCloudPlatform("AWS");
String id = getCloudbreakClient().networkEndpoint().postPrivate(networkRequest).getId().toString();
getItContext().putContextParam(CloudbreakITContextConstants.NETWORK_ID, id, true);
}
private List<Output> getOutputForRequest(String vpcStackName, AmazonCloudFormationClient client) {
int tried = 0;
while (tried < MAX_TRY) {
LOGGER.info("checking vpc stack creation result, tried: " + tried + "/" + MAX_TRY);
DescribeStacksRequest describeStacksRequest = new DescribeStacksRequest();
describeStacksRequest.withStackName(vpcStackName);
Stack resultStack = client.describeStacks(describeStacksRequest).getStacks().get(0);
StackStatus stackStatus = StackStatus.valueOf(resultStack.getStackStatus());
if (FAILED_STATUSES.contains(stackStatus)) {
LOGGER.error("stack creation failed: ", stackStatus);
throw new RuntimeException();
} else if (CREATE_COMPLETE.equals(stackStatus)) {
return resultStack.getOutputs();
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
LOGGER.error("thread sleep interrupted", e);
}
tried++;
}
throw new RuntimeException("vpc creation timed out");
}
private CreateStackRequest createStackRequest(String vpcStackName, String vpcName, String vpcCFTemplateString) {
CreateStackRequest createStackRequest = new CreateStackRequest();
Parameter vpcNameParameter = new Parameter();
vpcNameParameter.setParameterKey("VpcName");
vpcNameParameter.setParameterValue(vpcName);
createStackRequest.withParameters(vpcNameParameter);
createStackRequest.withStackName(vpcStackName);
createStackRequest.withTemplateBody(vpcCFTemplateString);
return createStackRequest;
}
}