package com.sequenceiq.it.cloudbreak;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.testng.ITestContext;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import com.sequenceiq.cloudbreak.api.endpoint.BlueprintEndpoint;
import com.sequenceiq.cloudbreak.api.endpoint.CredentialEndpoint;
import com.sequenceiq.cloudbreak.api.endpoint.NetworkEndpoint;
import com.sequenceiq.cloudbreak.api.endpoint.SecurityGroupEndpoint;
import com.sequenceiq.cloudbreak.api.endpoint.StackEndpoint;
import com.sequenceiq.cloudbreak.api.endpoint.TemplateEndpoint;
import com.sequenceiq.cloudbreak.client.CloudbreakClient;
import com.sequenceiq.it.IntegrationTestContext;
import com.sequenceiq.it.SuiteContext;
import com.sequenceiq.it.cloudbreak.config.ITProps;
import com.sequenceiq.it.config.IntegrationTestConfiguration;
import com.sequenceiq.it.util.CleanupService;
@ContextConfiguration(classes = IntegrationTestConfiguration.class, initializers = ConfigFileApplicationContextInitializer.class)
public class CloudbreakTestSuiteInitializer extends AbstractTestNGSpringContextTests {
private static final int WITH_TYPE_LENGTH = 4;
private static final Logger LOG = LoggerFactory.getLogger(CloudbreakTestSuiteInitializer.class);
@Value("${integrationtest.cloudbreak.server}")
private String defaultCloudbreakServer;
@Value("${integrationtest.testsuite.cleanUpOnFailure}")
private boolean cleanUpOnFailure;
@Value("${integrationtest.defaultBlueprintName}")
private String defaultBlueprintName;
@Value("${integrationtest.testsuite.skipRemainingTestsAfterOneFailed}")
private boolean skipRemainingSuiteTestsAfterOneFailed;
@Value("${integrationtest.cleanup.cleanupBeforeStart}")
private boolean cleanUpBeforeStart;
@Value("${integrationtest.ambari.defaultAmbariUser}")
private String defaultAmbariUser;
@Value("${integrationtest.ambari.defaultAmbariPassword}")
private String defaultAmbariPassword;
@Value("${integrationtest.ambari.defaultAmbariPort}")
private String defaultAmbariPort;
@Value("${server.contextPath:/cb}")
private String cbRootContextPath;
@Inject
private ITProps itProps;
@Inject
private TemplateAdditionHelper templateAdditionHelper;
@Inject
private SuiteContext suiteContext;
@Inject
private CleanupService cleanUpService;
private IntegrationTestContext itContext;
@BeforeSuite(dependsOnGroups = "suiteInit")
public void initContext(ITestContext testContext) throws Exception {
// Workaround of https://jira.spring.io/browse/SPR-4072
springTestContextBeforeTestClass();
springTestContextPrepareTestInstance();
itContext = suiteContext.getItContext(testContext.getSuite().getName());
}
@BeforeSuite(dependsOnMethods = "initContext")
@Parameters({"cloudbreakServer", "cloudProvider", "credentialName", "instanceGroups", "hostGroups", "blueprintName",
"stackName", "networkName", "securityGroupName" })
public void initCloudbreakSuite(@Optional("") String cloudbreakServer, @Optional("") String cloudProvider, @Optional("") String credentialName,
@Optional("") String instanceGroups, @Optional("") String hostGroups, @Optional("") String blueprintName,
@Optional("") String stackName, @Optional("") String networkName, @Optional("") String securityGroupName) {
cloudbreakServer = StringUtils.hasLength(cloudbreakServer) ? cloudbreakServer : defaultCloudbreakServer;
itContext.putContextParam(CloudbreakITContextConstants.SKIP_REMAINING_SUITETEST_AFTER_ONE_FAILED, skipRemainingSuiteTestsAfterOneFailed);
itContext.putContextParam(CloudbreakITContextConstants.CLOUDBREAK_SERVER, cloudbreakServer);
itContext.putContextParam(CloudbreakITContextConstants.CLOUDPROVIDER, cloudProvider);
String identity = itContext.getContextParam(IntegrationTestContext.IDENTITY_URL);
String user = itContext.getContextParam(IntegrationTestContext.AUTH_USER);
String password = itContext.getContextParam(IntegrationTestContext.AUTH_PASSWORD);
CloudbreakClient cloudbreakClient = new CloudbreakClient.CloudbreakClientBuilder(cloudbreakServer + cbRootContextPath, identity, "cloudbreak_shell")
.withCertificateValidation(false).withDebug(true).withCredential(user, password).build();
itContext.putContextParam(CloudbreakITContextConstants.CLOUDBREAK_CLIENT, cloudbreakClient);
if (cleanUpBeforeStart) {
cleanUpService.deleteTestStacksAndResources(cloudbreakClient);
}
putBlueprintToContextIfExist(
itContext.getContextParam(CloudbreakITContextConstants.CLOUDBREAK_CLIENT, CloudbreakClient.class).blueprintEndpoint(), blueprintName);
putNetworkToContext(
itContext.getContextParam(CloudbreakITContextConstants.CLOUDBREAK_CLIENT, CloudbreakClient.class).networkEndpoint(), cloudProvider, networkName);
putSecurityGroupToContext(itContext.getContextParam(CloudbreakITContextConstants.CLOUDBREAK_CLIENT, CloudbreakClient.class).securityGroupEndpoint(),
cloudProvider, securityGroupName);
putCredentialToContext(
itContext.getContextParam(CloudbreakITContextConstants.CLOUDBREAK_CLIENT, CloudbreakClient.class).credentialEndpoint(), cloudProvider,
credentialName);
putStackToContextIfExist(
itContext.getContextParam(CloudbreakITContextConstants.CLOUDBREAK_CLIENT, CloudbreakClient.class).stackEndpoint(), stackName);
if (StringUtils.hasLength(instanceGroups)) {
List<String[]> instanceGroupStrings = templateAdditionHelper.parseCommaSeparatedRows(instanceGroups);
itContext.putContextParam(CloudbreakITContextConstants.TEMPLATE_ID,
createInstanceGroups(itContext.getContextParam(CloudbreakITContextConstants.CLOUDBREAK_CLIENT, CloudbreakClient.class).templateEndpoint(),
instanceGroupStrings));
}
if (StringUtils.hasLength(hostGroups)) {
List<String[]> hostGroupStrings = templateAdditionHelper.parseCommaSeparatedRows(hostGroups);
itContext.putContextParam(CloudbreakITContextConstants.HOSTGROUP_ID, createHostGroups(hostGroupStrings));
}
}
@BeforeSuite(dependsOnMethods = "initContext")
@Parameters({"ambariUser", "ambariPassword", "ambariPort"})
public void initAmbariCredentials(@Optional("") String ambariUser, @Optional("") String ambariPassword, @Optional("") String ambariPort) {
putAmbariCredentialsToContext(ambariUser, ambariPassword, ambariPort);
}
private void putBlueprintToContextIfExist(BlueprintEndpoint endpoint, String blueprintName) {
endpoint.getPublics();
if (StringUtils.isEmpty(blueprintName)) {
blueprintName = defaultBlueprintName;
}
if (StringUtils.hasLength(blueprintName)) {
String resourceId = endpoint.getPublic(blueprintName).getId().toString();
if (resourceId != null) {
itContext.putContextParam(CloudbreakITContextConstants.BLUEPRINT_ID, resourceId);
}
}
}
private void putAmbariCredentialsToContext(String ambariUser, String ambariPassword, String ambariPort) {
if (StringUtils.isEmpty(ambariUser)) {
ambariUser = defaultAmbariUser;
}
if (StringUtils.isEmpty(ambariPassword)) {
ambariPassword = defaultAmbariPassword;
}
if (StringUtils.isEmpty(ambariPort)) {
ambariPort = defaultAmbariPort;
}
itContext.putContextParam(CloudbreakITContextConstants.AMBARI_USER_ID, ambariUser);
itContext.putContextParam(CloudbreakITContextConstants.AMBARI_PASSWORD_ID, ambariPassword);
itContext.putContextParam(CloudbreakITContextConstants.AMBARI_PORT_ID, ambariPort);
}
private void putNetworkToContext(NetworkEndpoint endpoint, String cloudProvider, String networkName) {
endpoint.getPublics();
if (StringUtils.isEmpty(networkName)) {
networkName = itProps.getDefaultNetwork(cloudProvider);
}
if (StringUtils.hasLength(networkName)) {
Long resourceId = endpoint.getPublic(networkName).getId();
if (resourceId != null) {
itContext.putContextParam(CloudbreakITContextConstants.NETWORK_ID, resourceId.toString());
}
}
}
private void putSecurityGroupToContext(SecurityGroupEndpoint endpoint, String cloudProvider, String securityGroupName) {
endpoint.getPublics();
if (StringUtils.isEmpty(securityGroupName)) {
securityGroupName = itProps.getDefaultSecurityGroup(cloudProvider);
}
if (StringUtils.hasLength(securityGroupName)) {
try {
Long resourceId = endpoint.getPublic(securityGroupName).getId();
itContext.putContextParam(CloudbreakITContextConstants.SECURITY_GROUP_ID, resourceId.toString());
} catch (Exception e) {
LOG.warn("Could not set security group id", e);
}
}
}
private void putStackToContextIfExist(StackEndpoint endpoint, String stackName) {
if (StringUtils.hasLength(stackName)) {
Long resourceId = endpoint.getPublic(stackName).getId();
itContext.putContextParam(CloudbreakITContextConstants.STACK_ID, resourceId.toString());
}
}
private void putCredentialToContext(CredentialEndpoint endpoint, String cloudProvider, String credentialName) {
if (StringUtils.isEmpty(credentialName)) {
String defaultCredentialName = itProps.getCredentialName(cloudProvider);
if (!"__ignored__".equals(defaultCredentialName)) {
credentialName = defaultCredentialName;
}
}
if (StringUtils.hasLength(credentialName)) {
Long resourceId = endpoint.getPublic(credentialName).getId();
itContext.putContextParam(CloudbreakITContextConstants.CREDENTIAL_ID, resourceId.toString());
}
}
private List<InstanceGroup> createInstanceGroups(TemplateEndpoint endpoint, List<String[]> instanceGroupStrings) {
List<InstanceGroup> instanceGroups = new ArrayList<>();
for (String[] instanceGroupStr : instanceGroupStrings) {
String type = instanceGroupStr.length == WITH_TYPE_LENGTH ? instanceGroupStr[WITH_TYPE_LENGTH - 1] : "CORE";
instanceGroups.add(new InstanceGroup(endpoint.getPublic(instanceGroupStr[0]).getId().toString(), instanceGroupStr[1],
Integer.parseInt(instanceGroupStr[2]), type));
}
return instanceGroups;
}
private List<HostGroup> createHostGroups(List<String[]> hostGroupStrings) {
List<HostGroup> hostGroups = new ArrayList<>();
for (String[] hostGroupStr : hostGroupStrings) {
hostGroups.add(new HostGroup(hostGroupStr[0], hostGroupStr[1], Integer.valueOf(hostGroupStr[2])));
}
return hostGroups;
}
@AfterSuite(alwaysRun = true)
@Parameters("cleanUp")
public void cleanUp(@Optional("true") boolean cleanUp) {
if (isCleanUpNeeded(cleanUp)) {
CloudbreakClient cloudbreakClient = itContext.getContextParam(CloudbreakITContextConstants.CLOUDBREAK_CLIENT, CloudbreakClient.class);
String stackId = itContext.getCleanUpParameter(CloudbreakITContextConstants.STACK_ID);
cleanUpService.deleteStackAndWait(cloudbreakClient, stackId);
List<InstanceGroup> instanceGroups = itContext.getCleanUpParameter(CloudbreakITContextConstants.TEMPLATE_ID, List.class);
if (instanceGroups != null && !instanceGroups.isEmpty()) {
Set<String> deletedTemplates = new HashSet<>();
for (InstanceGroup ig : instanceGroups) {
if (!deletedTemplates.contains(ig.getTemplateId())) {
cleanUpService.deleteTemplate(cloudbreakClient, ig.getTemplateId());
deletedTemplates.add(ig.getTemplateId());
}
}
}
Set<Long> recipeIds = itContext.getContextParam(CloudbreakITContextConstants.RECIPE_ID, Set.class);
if (recipeIds != null) {
for (Long recipeId : recipeIds) {
cleanUpService.deleteRecipe(cloudbreakClient, recipeId);
}
}
cleanUpService.deleteCredential(cloudbreakClient, itContext.getCleanUpParameter(CloudbreakITContextConstants.CREDENTIAL_ID));
cleanUpService.deleteBlueprint(cloudbreakClient, itContext.getCleanUpParameter(CloudbreakITContextConstants.BLUEPRINT_ID));
cleanUpService.deleteNetwork(cloudbreakClient, itContext.getCleanUpParameter(CloudbreakITContextConstants.NETWORK_ID));
cleanUpService.deleteSecurityGroup(cloudbreakClient, itContext.getCleanUpParameter(CloudbreakITContextConstants.SECURITY_GROUP_ID));
cleanUpService.deleteRdsConfigs(cloudbreakClient, itContext.getCleanUpParameter(CloudbreakITContextConstants.RDS_CONFIG_ID));
}
}
private boolean isCleanUpNeeded(boolean cleanUp) {
boolean noTestsFailed = CollectionUtils.isEmpty(itContext.getContextParam(CloudbreakITContextConstants.FAILED_TESTS, List.class));
return cleanUp && (cleanUpOnFailure || noTestsFailed);
}
}