/**
* Copyright (C) 2015 Orange
* 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.francetelecom.clara.cloud.paas.it.services;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.francetelecom.clara.cloud.core.service.ManageEnvironment;
import com.francetelecom.clara.cloud.core.service.exception.ObjectNotFoundException;
import com.francetelecom.clara.cloud.deployment.logical.service.ManageLogicalDeployment;
import com.francetelecom.clara.cloud.logicalmodel.*;
import com.francetelecom.clara.cloud.paas.it.services.helper.PaasServicesEnvITHelper;
import com.francetelecom.clara.cloud.services.dto.EnvironmentDetailsDto;
import com.francetelecom.clara.cloud.services.dto.EnvironmentDto;
import com.francetelecom.clara.cloud.services.dto.LinkDto;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.io.StringReader;
import java.util.*;
import static org.junit.Assert.assertNotNull;
@ContextConfiguration(classes = PaasServicesEnvConfigProbeITContext.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class PaasServicesEnvConfigProbeIT {
protected static Logger logger = LoggerFactory.getLogger(PaasServicesEnvConfigProbeIT.class);
RestTemplate restTemplate = new RestTemplate();
@Autowired(required = true)
private PaasServicesEnvITHelper paasServicesEnvITHelper;
private static PaasServicesEnvITHelper sPaasServicesEnvITHelper;
@Autowired(required = true)
private ManageEnvironment manageEnvironment;
@Autowired(required = true)
private ManageLogicalDeployment manageLogicalDeployment;
private String environmentUID;
private int logicalDeploymentID;
@Before
public void setUp() {
paasServicesEnvITHelper.setDefaultConfigurationItName();
PaasServicesEnvITHelper.checkThatAutowiredFieldIsNotNull(paasServicesEnvITHelper);
paasServicesEnvITHelper.setMaxSessions(10);
paasServicesEnvITHelper.setMaxRequests(200);
paasServicesEnvITHelper.setEnvType(EnvironmentDto.EnvironmentTypeEnum.DEVELOPMENT);
paasServicesEnvITHelper.setUp();
environmentUID = paasServicesEnvITHelper.getEnvironmentUID();
logicalDeploymentID = paasServicesEnvITHelper.getLogicalDeploymentID();
sPaasServicesEnvITHelper = paasServicesEnvITHelper;
}
@AfterClass
static public void tearDown() {
if (sPaasServicesEnvITHelper != null) {
sPaasServicesEnvITHelper.tearDown();
}
}
@Test
public void application_should_be_accessible() {
paasServicesEnvITHelper.application_should_be_accessible(true);
}
/**
* assert that properties are available for each access URL
*/
@Test
public void config_properties_should_be_available_for_each_access_url() throws ObjectNotFoundException {
EnvironmentDetailsDto envDto = manageEnvironment.findEnvironmentDetails(environmentUID);
// for each access link we assert that properties are available
for (LinkDto link : envDto.getSpecificLinkDto(LinkDto.LinkTypeEnum.ACCESS_LINK)) {
logger.info("Checking config properties at :" + link.getUrl());
Properties configProperties = getVarEnvAsProperties(link);
Assert.assertNotNull(configProperties);
Assert.assertNotNull(configProperties.stringPropertyNames());
String propertiesListMessage = "Config properties available at " + link.getUrl();
for (String name : configProperties.stringPropertyNames()) {
propertiesListMessage += "\n" + name;
}
logger.info(propertiesListMessage);
}
}
/**
* assert that properties are the ones registered in logical model for each access URL
*/
@Test
public void config_properties_names_should_be_correct() throws ObjectNotFoundException {
EnvironmentDetailsDto envDto = manageEnvironment.findEnvironmentDetails(environmentUID);
// get logical deployment
LogicalDeployment lm = manageLogicalDeployment.findLogicalDeployment(logicalDeploymentID);
// get all execution node of the logical deployment
List<ProcessingNode> nodes = lm.listProcessingNodes();
// get Map of linkDtos of the environment
Map<String, List<LinkDto>> linksDtosMap = envDto.getLinkDtoMap();
// iterate on all execution node of the logical deployment to find access url
for (ProcessingNode node : nodes) {
// list all logical execution node service association
List<LogicalNodeServiceAssociation> nodeServiceAssociations = node.listLogicalServicesAssociations();
for (LogicalNodeServiceAssociation association : nodeServiceAssociations) {
// looking for LogicalWebGui service to get its access URL
if (association.getLogicalService() instanceof LogicalWebGUIService) {
LogicalWebGUIService webGUIService = (LogicalWebGUIService) association.getLogicalService();
// get the list of linkDto of the selected webGui service
List<LinkDto> linkDtos = linksDtosMap.get(webGUIService.getName());
for (LinkDto link : linkDtos) {
// select only linkDto of ACCESS_LINK type
if (link.getLinkType() == LinkDto.LinkTypeEnum.ACCESS_LINK) {
logger.info("Checking config properties at :" + link.getUrl());
Properties configProperties = getVarEnvAsProperties(link);
Assert.assertNotNull(configProperties);
Properties expectedProperties = getExpectedConfigPropertiesForNode(node);
String missingProperties = "";
for (String name : expectedProperties.stringPropertyNames()) {
if (!configProperties.containsKey(convertPropertyNameToMatchVariableEnvironmentConstraint(name))) {
missingProperties += name + ", ";
}
}
Assert.assertTrue("properties not found: " + missingProperties + " ;url=" + link.getUrl(), missingProperties.length() == 0);
}
}
}
}
}
}
private String convertPropertyNameToMatchVariableEnvironmentConstraint(String key) {
return key.replace(".", "_");
}
private boolean containsProperty(Properties properties, String key) {
String name=key;
if (key.contains(".")) {
//for performance, should usually match this case
name = key.replace(".","_");
}
if (properties.contains(name)){
return true;
}
//handle other case
int count= StringUtils.countOccurrencesOf(key, ".");
final String[] keysExplodedWithoutDot = key.split(".");
StringBuilder newName=new StringBuilder(name);
List<Integer> dotIndexes = new ArrayList<Integer>();
for(int dotIndex = newName.indexOf(".");dotIndex<newName.length() && dotIndex != -1;) {
dotIndexes.add(dotIndex);
dotIndex = newName.indexOf(".", 1);
newName.setCharAt(dotIndex,'_');
logger.info("Trying with name {}",newName);
if (properties.containsKey(newName.toString())){
return true;
}
}
return false;
}
/**
* assert that properties values are the ones registered in logical model for each access URL
*/
@Test
public void config_properties_values_should_be_correct() throws ObjectNotFoundException {
EnvironmentDetailsDto envDto = manageEnvironment.findEnvironmentDetails(environmentUID);
// get logical deployment
LogicalDeployment lm = manageLogicalDeployment.findLogicalDeployment(logicalDeploymentID);
// get all execution node of the logical deployment
List<ProcessingNode> nodes = lm.listProcessingNodes();
// get Map of linkDtos of the environment
Map<String, List<LinkDto>> linksDtosMap = envDto.getLinkDtoMap();
// iterate on all execution node of the logical deployment to find access url
for (ProcessingNode node : nodes) {
// list all logical execution node service association
List<LogicalNodeServiceAssociation> nodeServiceAssociations = node.listLogicalServicesAssociations();
for (LogicalNodeServiceAssociation association : nodeServiceAssociations) {
// looking for LogicalWebGui service to get its access URL
if (association.getLogicalService() instanceof LogicalWebGUIService) {
LogicalWebGUIService webGUIService = (LogicalWebGUIService) association.getLogicalService();
// get the list of linkDto of the selected webGui service
List<LinkDto> linkDtos = linksDtosMap.get(webGUIService.getName());
for (LinkDto link : linkDtos) {
// select only linkDto of ACCESS_LINK type
if (link.getLinkType() == LinkDto.LinkTypeEnum.ACCESS_LINK) {
logger.info("Checking config properties at :" + link.getUrl());
Properties configProperties = getVarEnvAsProperties(link);
Assert.assertNotNull(configProperties);
Set<String> registeredProperties = configProperties.stringPropertyNames();
Properties expectedProperties = getExpectedConfigPropertiesForNode(node);
String missingProperties = "";
for (String name : expectedProperties.stringPropertyNames()) {
if (!configProperties.containsKey(convertPropertyNameToMatchVariableEnvironmentConstraint(name))) {
missingProperties += name + ", ";
}
String expectedValue = expectedProperties.getProperty(name);
String actualValue = configProperties.getProperty(convertPropertyNameToMatchVariableEnvironmentConstraint(name));
Assert.assertEquals("property value is not the expected one; property name=" + name + " ;url=" + link.getUrl(), expectedValue, actualValue);
}
Assert.assertTrue("properties not found: " + missingProperties + " ;url=" + link.getUrl(), missingProperties.length() == 0);
}
}
}
}
}
}
/*
check here for existing CF VAR http://docs.run.pivotal.io/devguide/deploy-apps/environment-variable.html
*/
@Test
public void should_ensure_CF_expose_default_entry() throws ObjectNotFoundException, IOException {
String EXPECTED_VCAP_APPLICATION_VARENV = "VCAP_APPLICATION";
String EXPECTED_VCAP_SERVICES_VARENV = "VCAP_SERVICES";
EnvironmentDetailsDto envDto = manageEnvironment.findEnvironmentDetails(environmentUID);
Map<String, List<LinkDto>> linkDtosMap = envDto.getLinkDtoMap();
LogicalDeployment logicalModel = manageLogicalDeployment.findLogicalDeployment(logicalDeploymentID);
// Iterate over all web gui services of the model
Set<LogicalWebGUIService> webGuiServices = logicalModel.listLogicalServices(LogicalWebGUIService.class);
Assert.assertTrue("This test assumes that at least one webgui service is defined in logical model", webGuiServices.size() > 0);
for (LogicalWebGUIService webGuiService : webGuiServices) {
logger.debug("Checking web gui url is registred as env property for web gui with label " + webGuiService.getLabel());
// Retrieve access link
List<LinkDto> linkDtos = linkDtosMap.get(webGuiService.getName());
LinkDto webUiLink = null;
for (LinkDto link : linkDtos) {
if (link.getLinkType() == LinkDto.LinkTypeEnum.ACCESS_LINK) {
webUiLink = link;
}
}
Assert.assertNotNull("No access link found for web gui " + webGuiService.getLabel(), webUiLink);
logger.debug("Access link is:" + webUiLink.getUrl().toExternalForm());
// Retrieve properties for access link
Properties varEnvs = getVarEnvAsProperties(webUiLink);
Assert.assertNotNull(varEnvs);
ObjectMapper mapper = new ObjectMapper();
JsonNode vcapApplication = mapper.readTree(varEnvs.getProperty(EXPECTED_VCAP_APPLICATION_VARENV, "{" + EXPECTED_VCAP_APPLICATION_VARENV + " is NOT FOUND}"));
final List<String> application_uris = vcapApplication.findValuesAsText("application_uris");
String expectedWebUiUrl = webUiLink.getUrl().toExternalForm();
boolean exposedUrlFound = false;
for (String application_uri : application_uris) {
if (expectedWebUiUrl.contains(application_uri)) {
exposedUrlFound = true;
}
}
Assert.assertTrue("Should have found webUI " + expectedWebUiUrl + " in " + EXPECTED_VCAP_APPLICATION_VARENV, exposedUrlFound);
mapper = new ObjectMapper();
mapper.readTree(varEnvs.getProperty(EXPECTED_VCAP_SERVICES_VARENV, "{" + EXPECTED_VCAP_SERVICES_VARENV + " is NOT FOUND}"));
// Assert that the webUiUrlJndi property is defined
// Assert.assertTrue("The jndi entry [" + expectedJndiPropertyName + "] corresponding to web gui url is not found as a config property", registeredVarEnvs.contains(expectedJndiPropertyName));
// Assert that the webUiUrlJndi property value equals to access link
// Assert.assertEquals("Incorrect value for the jndi property " + expectedJndiPropertyName, expectedJndiPropertyValue, varEnvs.getProperty(expectedJndiPropertyName));
}
}
/**
* call getConfigProperties of the config probe for the specified access url
*/
Properties getConfigPropertiesForUrl(LinkDto link) {
Properties result = new Properties();
Properties metaProperties = paasServicesEnvITHelper.executeRestRequest(link, "env/", Properties.class);
assertNotNull(metaProperties);
HashMap<String, String> systemProperties = (HashMap<String, String>) metaProperties.get("systemProperties");
result.putAll(systemProperties);
return result;
}
Properties getVarEnvAsProperties(LinkDto link) {
Properties result = new Properties();
Properties metaProperties = paasServicesEnvITHelper.executeRestRequest(link, "env/", Properties.class);
assertNotNull(metaProperties);
HashMap<String, String> systemEnvironment = (HashMap<String, String>) metaProperties.get("systemEnvironment");
result.putAll(systemEnvironment);
return result;
}
/**
* return the list of config properties that are expected to be registered on an access url
*
* @param node JeeProcessing
* @return
* @throws ObjectNotFoundException
*/
private Properties getExpectedConfigPropertiesForNode(
ProcessingNode node) throws ObjectNotFoundException {
Properties properties = new Properties();
Assert.assertNotNull("no execution node found with name " + node.getName());
// Getting config sets attached to this node
List<LogicalConfigService> configSets = node.listLogicalServices(LogicalConfigService.class);
for (LogicalConfigService configSet : configSets) {
String keyPrefix = configSet.getKeyPrefix();
Properties props = new Properties();
try {
props.load(new StringReader(configSet.getConfigSetContent()));
} catch (IOException e) {
String message = "Incorrect properties format for configSet=" + getClass().getSimpleName();
logger.error(message, e);
}
for (String name : props.stringPropertyNames()) {
properties.put(keyPrefix + name, props.getProperty(name));
}
}
return properties;
}
}