Repository: stratos Updated Branches: refs/heads/stratos-4.1.x 270066786 -> 35cadf67c
Closing STRATOS-1607 - Integration tests for metadata service Project: http://git-wip-us.apache.org/repos/asf/stratos/repo Commit: http://git-wip-us.apache.org/repos/asf/stratos/commit/35cadf67 Tree: http://git-wip-us.apache.org/repos/asf/stratos/tree/35cadf67 Diff: http://git-wip-us.apache.org/repos/asf/stratos/diff/35cadf67 Branch: refs/heads/stratos-4.1.x Commit: 35cadf67ce91a07704487df4724acc114b643a66 Parents: 2700667 Author: Akila Perera <[email protected]> Authored: Fri Nov 6 21:56:43 2015 +0530 Committer: Akila Perera <[email protected]> Committed: Fri Nov 6 21:57:18 2015 +0530 ---------------------------------------------------------------------- .../metadata/client/beans/PropertyBean.java | 19 +- .../integration/common/rest/RestClient.java | 122 +++-- .../application/MetadataServiceTestCase.java | 447 +++++++++++++++++++ .../SampleApplicationStartupTestCase.java | 15 +- ...pplication-policy-metadata-service-test.json | 17 + .../application-metadata-service-test-1.json | 24 + .../application-metadata-service-test-2.json | 24 + ...utoscaling-policy-metadata-service-test.json | 14 + .../c1-application-metadata-service-test.json | 45 ++ ...deployment-policy-metadata-service-test.json | 18 + ...network-partition-metadata-service-test.json | 15 + 11 files changed, 709 insertions(+), 51 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/components/org.apache.stratos.metadata.client/src/main/java/org/apache/stratos/metadata/client/beans/PropertyBean.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.metadata.client/src/main/java/org/apache/stratos/metadata/client/beans/PropertyBean.java b/components/org.apache.stratos.metadata.client/src/main/java/org/apache/stratos/metadata/client/beans/PropertyBean.java index 7fae6a6..92c2250 100644 --- a/components/org.apache.stratos.metadata.client/src/main/java/org/apache/stratos/metadata/client/beans/PropertyBean.java +++ b/components/org.apache.stratos.metadata.client/src/main/java/org/apache/stratos/metadata/client/beans/PropertyBean.java @@ -37,6 +37,11 @@ public class PropertyBean { this.values.add(value); } + public PropertyBean(String key, List<String> values) { + this.key = key; + this.values = values; + } + public String getKey() { return key; } @@ -45,12 +50,6 @@ public class PropertyBean { this.key = key; } - public String[] getValues() { - String[] values = new String[this.values.size()]; - values = this.values.toArray(values); - return values; - } - public void setValues(String value) { this.values.add(value); } @@ -62,4 +61,12 @@ public class PropertyBean { public void addValue(String value) { this.values.add(value); } + + public List<String> getValues() { + return values; + } + + public void setValues(List<String> values) { + this.values = values; + } } http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/products/stratos/modules/integration/test-common/src/main/java/org/apache/stratos/integration/common/rest/RestClient.java ---------------------------------------------------------------------- diff --git a/products/stratos/modules/integration/test-common/src/main/java/org/apache/stratos/integration/common/rest/RestClient.java b/products/stratos/modules/integration/test-common/src/main/java/org/apache/stratos/integration/common/rest/RestClient.java index fca36a1..d65924c 100644 --- a/products/stratos/modules/integration/test-common/src/main/java/org/apache/stratos/integration/common/rest/RestClient.java +++ b/products/stratos/modules/integration/test-common/src/main/java/org/apache/stratos/integration/common/rest/RestClient.java @@ -17,6 +17,7 @@ package org.apache.stratos.integration.common.rest; import com.google.gson.*; +import com.google.gson.reflect.TypeToken; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -27,13 +28,9 @@ import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContextBuilder; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingClientConnectionManager; import org.apache.stratos.integration.common.RestConstants; import org.apache.stratos.metadata.client.beans.PropertyBean; -import org.apache.stratos.metadata.client.exception.RestClientException; import org.apache.stratos.metadata.client.rest.HTTPConnectionManager; import java.io.File; @@ -41,9 +38,7 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.lang.reflect.Type; import java.net.URI; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; import java.util.List; /** @@ -280,7 +275,6 @@ public class RestClient { throws Exception { URI uri = new URIBuilder( this.securedEndpoint + RestConstants.METADATA_API + "/applications/" + appId + "/properties").build(); - log.info("Metadata endpoint resource: " + uri.toString()); PropertyBean property = new PropertyBean(propertyKey, propertyValue); HttpResponse response; HttpPost postRequest = null; @@ -354,18 +348,9 @@ public class RestClient { } finally { releaseConnection(getRequest); } - Gson gson = new GsonBuilder().registerTypeAdapter(List.class, new JsonSerializer<List<?>>() { - @Override - public JsonElement serialize(List<?> list, Type t, JsonSerializationContext jsc) { - if (list.size() == 1) { - // Don't put single element lists in a json array - return new Gson().toJsonTree(list.get(0)); - } else { - return new Gson().toJsonTree(list); - } - } - }).create(); - return gson.fromJson(response.getContent(), PropertyBean.class); + Gson gson = new GsonBuilder().registerTypeAdapter(PropertyBean.class, new PropertyBeanDeserializer()).create(); + return gson.fromJson(response.getContent(), new TypeToken<PropertyBean>() { + }.getType()); } public PropertyBean getApplicationProperty(String appId, String propertyName, String accessToken) throws Exception { @@ -377,24 +362,17 @@ public class RestClient { try { getRequest = new HttpGet(uri); getRequest.addHeader("Content-Type", "application/json"); - String bearerAuth = "Bearer " + accessToken; - getRequest.addHeader("Authorization", bearerAuth); + if (StringUtils.isNotEmpty(accessToken)) { + String bearerAuth = "Bearer " + accessToken; + getRequest.addHeader("Authorization", bearerAuth); + } response = httpClient.execute(getRequest, new HttpResponseHandler()); } finally { releaseConnection(getRequest); } - Gson gson = new GsonBuilder().registerTypeAdapter(List.class, new JsonSerializer<List<?>>() { - @Override - public JsonElement serialize(List<?> list, Type t, JsonSerializationContext jsc) { - if (list.size() == 1) { - // Don't put single element lists in a json array - return new Gson().toJsonTree(list.get(0)); - } else { - return new Gson().toJsonTree(list); - } - } - }).create(); - return gson.fromJson(response.getContent(), PropertyBean.class); + Gson gson = new GsonBuilder().registerTypeAdapter(PropertyBean.class, new PropertyBeanDeserializer()).create(); + return gson.fromJson(response.getContent(), new TypeToken<PropertyBean>() { + }.getType()); } public boolean deleteApplicationProperties(String appId, String accessToken) throws Exception { @@ -419,7 +397,64 @@ public class RestClient { throw new RuntimeException(response.getContent()); } } - throw new Exception("Null response received. Could not delete properties for application: " + appId); + throw new Exception( + String.format("Null response received. Could not delete properties for [application] %s", appId)); + } + + public boolean deleteApplicationProperty(String appId, String propertyName, String accessToken) throws Exception { + URI uri = new URIBuilder( + this.securedEndpoint + RestConstants.METADATA_API + "/applications/" + appId + "/properties/" + + propertyName).build(); + HttpResponse response; + HttpDelete httpDelete = null; + try { + httpDelete = new HttpDelete(uri); + httpDelete.addHeader("Content-Type", "application/json"); + String bearerAuth = "Bearer " + accessToken; + httpDelete.addHeader("Authorization", bearerAuth); + response = httpClient.execute(httpDelete, new HttpResponseHandler()); + } finally { + releaseConnection(httpDelete); + } + + if (response != null) { + if ((response.getStatusCode() >= 200) && (response.getStatusCode() < 300)) { + return true; + } else { + throw new RuntimeException(response.getContent()); + } + } + throw new Exception(String.format("Null response received. Could not delete [property] %s in [application] %s", + propertyName, appId)); + } + + public boolean deleteApplicationPropertyValue(String appId, String propertyName, String value, String accessToken) + throws Exception { + URI uri = new URIBuilder( + this.securedEndpoint + RestConstants.METADATA_API + "/applications/" + appId + "/properties/" + + propertyName + "/value/" + value).build(); + HttpResponse response; + HttpDelete httpDelete = null; + try { + httpDelete = new HttpDelete(uri); + httpDelete.addHeader("Content-Type", "application/json"); + String bearerAuth = "Bearer " + accessToken; + httpDelete.addHeader("Authorization", bearerAuth); + response = httpClient.execute(httpDelete, new HttpResponseHandler()); + } finally { + releaseConnection(httpDelete); + } + + if (response != null) { + if ((response.getStatusCode() >= 200) && (response.getStatusCode() < 300)) { + return true; + } else { + throw new RuntimeException(response.getContent()); + } + } + throw new Exception( + String.format("Null response received. Could not delete [value] %s, [property] %s in [application] %s", + value, propertyName, appId)); } /** @@ -455,4 +490,21 @@ public class RestClient { private String getUsernamePassword() { return this.userName + ":" + this.password; } + + class PropertyBeanDeserializer implements JsonDeserializer<PropertyBean> { + @Override + public PropertyBean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jObj = json.getAsJsonObject(); + JsonElement jElement = jObj.get("values"); + List<String> tags = new ArrayList<>(); + if (jElement.isJsonArray()) { + tags = context.deserialize(jElement.getAsJsonArray(), new TypeToken<List<String>>() { + }.getType()); + } else { + tags.add(jObj.getAsJsonPrimitive("values").getAsString()); + } + return new PropertyBean(jObj.getAsJsonPrimitive("key").getAsString(), tags); + } + } } http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/products/stratos/modules/integration/test-integration/src/test/java/org/apache/stratos/integration/tests/application/MetadataServiceTestCase.java ---------------------------------------------------------------------- diff --git a/products/stratos/modules/integration/test-integration/src/test/java/org/apache/stratos/integration/tests/application/MetadataServiceTestCase.java b/products/stratos/modules/integration/test-integration/src/test/java/org/apache/stratos/integration/tests/application/MetadataServiceTestCase.java new file mode 100644 index 0000000..9a40357 --- /dev/null +++ b/products/stratos/modules/integration/test-integration/src/test/java/org/apache/stratos/integration/tests/application/MetadataServiceTestCase.java @@ -0,0 +1,447 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.stratos.integration.tests.application; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.stratos.common.beans.application.ApplicationBean; +import org.apache.stratos.common.beans.policy.deployment.ApplicationPolicyBean; +import org.apache.stratos.integration.common.RestConstants; +import org.apache.stratos.integration.common.TopologyHandler; +import org.apache.stratos.integration.tests.StratosIntegrationTest; +import org.apache.stratos.messaging.domain.application.ApplicationStatus; +import org.apache.stratos.messaging.domain.topology.Member; +import org.apache.stratos.metadata.client.beans.PropertyBean; +import org.apache.stratos.mock.iaas.domain.MockInstanceMetadata; +import org.testng.Assert; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.testng.Assert.*; +import static org.testng.AssertJUnit.assertTrue; + +/** + * Deploy a sample application on mock IaaS and load test metadata service with high load of concurrent read/write + * operations from multiple clients + */ +public class MetadataServiceTestCase extends StratosIntegrationTest { + private static final Log log = LogFactory.getLog(MetadataServiceTestCase.class); + private static final String RESOURCES_PATH = "/metadata-service-test"; + private static final String PAYLOAD_PARAMETER_SEPARATOR = ","; + private static final String PAYLOAD_PARAMETER_NAME_VALUE_SEPARATOR = "="; + private static final String PAYLOAD_PARAMETER_TOKEN_KEY = "TOKEN"; + private static final String PAYLOAD_PARAMETER_APPLICATION_ID_KEY = "APPLICATION_ID"; + private static final String PAYLOAD_PARAMETER_CLUSTER_ID_KEY = "CLUSTER_ID"; + private GsonBuilder gsonBuilder = new GsonBuilder(); + private Gson gson = gsonBuilder.create(); + private TopologyHandler topologyHandler = TopologyHandler.getInstance(); + private String app1AccessToken; + private String app2AccessToken; + private String app1ClusterId; + private long startTime; + + public static final String NETWORK_PARTITION_ID = "network-partition-metadata-service-test"; + public static final String AUTOSCALE_POLICY_ID = "autoscaling-policy-metadata-service-test"; + public static final String CARTRIDGE_TYPE = "c1-application-metadata-service-test"; + public static final String APPLICATION_1_ID = "application-metadata-service-test-1"; + public static final String APPLICATION_2_ID = "application-metadata-service-test-2"; + public static final String APPLICATION_POLICY_ID = "application-policy-metadata-service-test"; + public static final String DEPLOYMENT_POLICY_ID = "deployment-policy-metadata-service-test"; + + @BeforeTest(timeOut = APPLICATION_TEST_TIMEOUT, + groups = { "stratos.application.deployment" }) + public void deployApplications() throws Exception { + startTime = System.currentTimeMillis(); + log.info("Adding autoscaling policy [autoscale policy id] " + AUTOSCALE_POLICY_ID); + boolean addedScalingPolicy = restClient.addEntity( + RESOURCES_PATH + RestConstants.AUTOSCALING_POLICIES_PATH + "/" + AUTOSCALE_POLICY_ID + ".json", + RestConstants.AUTOSCALING_POLICIES, RestConstants.AUTOSCALING_POLICIES_NAME); + assertTrue(addedScalingPolicy); + + log.info("Adding cartridge [cartridge type] " + CARTRIDGE_TYPE); + boolean addedC1 = restClient + .addEntity(RESOURCES_PATH + RestConstants.CARTRIDGES_PATH + "/" + CARTRIDGE_TYPE + ".json", + RestConstants.CARTRIDGES, RestConstants.CARTRIDGES_NAME); + assertTrue(addedC1); + + log.info("Adding network partition [network partition id] " + APPLICATION_1_ID); + boolean addedN1 = restClient.addEntity(RESOURCES_PATH + RestConstants.NETWORK_PARTITIONS_PATH + "/" + + NETWORK_PARTITION_ID + ".json", RestConstants.NETWORK_PARTITIONS, + RestConstants.NETWORK_PARTITIONS_NAME); + assertTrue(addedN1); + + log.info("Adding deployment policy [deployment policy id] " + DEPLOYMENT_POLICY_ID); + boolean addedDep = restClient.addEntity(RESOURCES_PATH + RestConstants.DEPLOYMENT_POLICIES_PATH + "/" + + DEPLOYMENT_POLICY_ID + ".json", RestConstants.DEPLOYMENT_POLICIES, + RestConstants.DEPLOYMENT_POLICIES_NAME); + assertTrue(addedDep); + + // add app-1 + log.info("Adding application [application id] " + APPLICATION_1_ID); + boolean addedApp1 = restClient.addEntity(RESOURCES_PATH + RestConstants.APPLICATIONS_PATH + "/" + + APPLICATION_1_ID + ".json", RestConstants.APPLICATIONS, RestConstants.APPLICATIONS_NAME); + assertEquals(addedApp1, true); + + ApplicationBean bean1 = (ApplicationBean) restClient + .getEntity(RestConstants.APPLICATIONS, APPLICATION_1_ID, ApplicationBean.class, + RestConstants.APPLICATIONS_NAME); + assertEquals(bean1.getApplicationId(), APPLICATION_1_ID); + + // add app-2 + log.info("Adding application [application id] " + APPLICATION_2_ID); + boolean addedApp2 = restClient.addEntity(RESOURCES_PATH + RestConstants.APPLICATIONS_PATH + "/" + + APPLICATION_2_ID + ".json", RestConstants.APPLICATIONS, RestConstants.APPLICATIONS_NAME); + assertEquals(addedApp2, true); + + ApplicationBean bean2 = (ApplicationBean) restClient + .getEntity(RestConstants.APPLICATIONS, APPLICATION_2_ID, ApplicationBean.class, + RestConstants.APPLICATIONS_NAME); + assertEquals(bean2.getApplicationId(), APPLICATION_2_ID); + + log.info("Adding application policy [application policy id] " + APPLICATION_POLICY_ID); + boolean addAppPolicy = restClient.addEntity(RESOURCES_PATH + RestConstants.APPLICATION_POLICIES_PATH + "/" + + APPLICATION_POLICY_ID + ".json", RestConstants.APPLICATION_POLICIES, + RestConstants.APPLICATION_POLICIES_NAME); + assertTrue(addAppPolicy); + + ApplicationPolicyBean policyBean = (ApplicationPolicyBean) restClient + .getEntity(RestConstants.APPLICATION_POLICIES, APPLICATION_POLICY_ID, ApplicationPolicyBean.class, + RestConstants.APPLICATION_POLICIES_NAME); + assertEquals(policyBean.getId(), APPLICATION_POLICY_ID); + + // deploy app-1 + log.info("Deploying application [application id] " + APPLICATION_1_ID + " using [application policy " + "id] " + + APPLICATION_POLICY_ID); + String resourcePath = RestConstants.APPLICATIONS + "/" + APPLICATION_1_ID + + RestConstants.APPLICATIONS_DEPLOY + "/" + APPLICATION_POLICY_ID; + boolean deployed = restClient.deployEntity(resourcePath, RestConstants.APPLICATIONS_NAME); + assertTrue(deployed); + + // deploy app-2 + log.info("Deploying application [application id] " + APPLICATION_2_ID + " using [application policy " + "id] " + + APPLICATION_POLICY_ID); + resourcePath = RestConstants.APPLICATIONS + "/" + APPLICATION_2_ID + + RestConstants.APPLICATIONS_DEPLOY + "/" + APPLICATION_POLICY_ID; + deployed = restClient.deployEntity(resourcePath, RestConstants.APPLICATIONS_NAME); + assertTrue(deployed); + + log.info("Waiting for application-1 status to become ACTIVE..."); + topologyHandler.assertApplicationStatus(bean1.getApplicationId(), ApplicationStatus.Active); + + log.info("Waiting for cluster status of application-1 to become ACTIVE..."); + topologyHandler.assertClusterActivation(bean1.getApplicationId()); + + log.info("Waiting for application-2 status to become ACTIVE..."); + topologyHandler.assertApplicationStatus(bean2.getApplicationId(), ApplicationStatus.Active); + + log.info("Waiting for cluster status of application-2 to become ACTIVE..."); + topologyHandler.assertClusterActivation(bean2.getApplicationId()); + + Properties app1PayloadProperties = getPayloadProperties(APPLICATION_1_ID); + app1AccessToken = app1PayloadProperties.getProperty(PAYLOAD_PARAMETER_TOKEN_KEY); + String app1Id = app1PayloadProperties.getProperty(PAYLOAD_PARAMETER_APPLICATION_ID_KEY); + Assert.assertEquals(app1Id, APPLICATION_1_ID, "Payload application id is not equal to deployed application id"); + app1ClusterId = app1PayloadProperties.getProperty(PAYLOAD_PARAMETER_CLUSTER_ID_KEY); + assertNotNull(app1AccessToken, "Access token is null in member payload"); + + Properties app2PayloadProperties = getPayloadProperties(APPLICATION_2_ID); + app2AccessToken = app2PayloadProperties.getProperty(PAYLOAD_PARAMETER_TOKEN_KEY); + String app2Id = app2PayloadProperties.getProperty(PAYLOAD_PARAMETER_APPLICATION_ID_KEY); + Assert.assertEquals(app2Id, APPLICATION_2_ID, "Payload application id is not equal to deployed application id"); + assertNotNull(app2AccessToken, "Access token is null in member payload"); + } + + private Properties getPayloadProperties(String applicationId) { + List<Member> memberList = topologyHandler.getMembersForApplication(applicationId); + Assert.assertTrue(memberList.size() > 0, + String.format("Active member list for application %s is empty", applicationId)); + MockInstanceMetadata mockInstanceMetadata = mockIaasApiClient.getInstance(memberList.get(0).getMemberId()); + String payloadString = mockInstanceMetadata.getPayload(); + log.info("Mock instance payload properties: " + payloadString); + + Properties payloadProperties = new Properties(); + String[] parameterArray = payloadString.split(PAYLOAD_PARAMETER_SEPARATOR); + for (String parameter : parameterArray) { + if (parameter != null) { + String[] nameValueArray = parameter.split(PAYLOAD_PARAMETER_NAME_VALUE_SEPARATOR, 2); + if ((nameValueArray.length == 2)) { + payloadProperties.put(nameValueArray[0], nameValueArray[1]); + } + } + } + return payloadProperties; + } + + @Test(timeOut = APPLICATION_TEST_TIMEOUT, + description = "Application startup, activation and metadata service basic test", + groups = { "stratos.application.deployment" }, + priority = 1) + public void testBasicOperations() throws Exception { + String key = "mykey"; + String val1 = "myval1"; + String val2 = "myval2"; + String val3 = "myval3"; + + log.info("Trying to add metadata for application:" + APPLICATION_1_ID + ", with app1AccessToken: " + + app1AccessToken); + boolean hasProperty1Added = restClient.addPropertyToApplication(APPLICATION_1_ID, key, val1, app1AccessToken); + Assert.assertTrue(hasProperty1Added, "Could not add metadata property1 to application: " + APPLICATION_1_ID); + + PropertyBean propertyBean1 = restClient.getApplicationProperty(APPLICATION_1_ID, key, app1AccessToken); + log.info("Retrieved metadata property: " + gson.toJson(propertyBean1)); + Assert.assertTrue(propertyBean1 != null && propertyBean1.getValues().size() > 0, "Empty property list"); + + boolean hasPropertiesAdded1 = propertyBean1.getValues().contains(val1); + Assert.assertTrue(hasPropertiesAdded1, "Metadata properties retrieved are not correct"); + + log.info("Trying to add metadata for application:" + APPLICATION_1_ID + ", with app1AccessToken: " + + app1AccessToken); + boolean hasProperty2Added = restClient.addPropertyToApplication(APPLICATION_1_ID, key, val2, app1AccessToken); + Assert.assertTrue(hasProperty2Added, "Could not add metadata property2 to application: " + APPLICATION_1_ID); + + PropertyBean propertyBean2 = restClient.getApplicationProperty(APPLICATION_1_ID, key, app1AccessToken); + log.info("Retrieved metadata property: " + gson.toJson(propertyBean2)); + Assert.assertTrue(propertyBean2 != null && propertyBean2.getValues().size() > 0, "Empty property list"); + + List<String> addedValues = new ArrayList<>(Arrays.asList(val1, val2)); + boolean hasPropertiesAdded2 = propertyBean2.getValues().containsAll(addedValues); + Assert.assertTrue(hasPropertiesAdded2, "Metadata properties retrieved are not correct"); + + log.info("Trying to add metadata for application:" + APPLICATION_1_ID + ", cluster:" + app1ClusterId + + ", with app1AccessToken: " + app1AccessToken); + restClient.addPropertyToCluster(APPLICATION_1_ID, app1ClusterId, key, val3, app1AccessToken); + PropertyBean propertyBean3 = restClient + .getClusterProperty(APPLICATION_1_ID, app1ClusterId, key, app1AccessToken); + log.info("Retrieved metadata property: " + gson.toJson(propertyBean3)); + Assert.assertTrue(propertyBean3 != null && propertyBean3.getValues().size() > 0, "Empty property list"); + + boolean hasPropertiesAdded3 = propertyBean3.getValues().contains(val3); + Assert.assertTrue(hasPropertiesAdded3, "Metadata properties retrieved are not correct"); + + // clean up property value + log.info("Trying to remove application property value"); + restClient.deleteApplicationPropertyValue(APPLICATION_1_ID, key, val2, app1AccessToken); + PropertyBean propertyBean4 = restClient.getApplicationProperty(APPLICATION_1_ID, key, app1AccessToken); + boolean hasPropertyValueRemoved = !propertyBean4.getValues().contains(val2); + Assert.assertTrue(hasPropertyValueRemoved, + String.format("Application [property] %s, [value] %s was not removed", key, val2)); + + log.info("Trying to remove application property"); + restClient.deleteApplicationProperty(APPLICATION_1_ID, key, app1AccessToken); + PropertyBean propertyBean5 = restClient.getApplicationProperty(APPLICATION_1_ID, key, app1AccessToken); + Assert.assertNull(propertyBean5, "Metadata properties have not been cleaned properly"); + + // clean up app metadata + restClient.deleteApplicationProperties(APPLICATION_1_ID, app1AccessToken); + PropertyBean propertyBeanCleaned = restClient.getApplicationProperty(APPLICATION_1_ID, key, app1AccessToken); + log.info("Retrieved metadata property: " + gson.toJson(propertyBeanCleaned)); + Assert.assertNull(propertyBeanCleaned, "Metadata properties have not been cleaned properly"); + + log.info("Metadata service basic test completed successfully"); + } + + @Test(timeOut = APPLICATION_TEST_TIMEOUT, + description = "Application startup, activation and metadata service concurrency test", + groups = { "stratos.application.deployment" }, + priority = 2) + public void metadataConcurrencyTest() throws Exception { + log.info("Starting multiple clients to add properties"); + ExecutorService taskExecutor = Executors.newFixedThreadPool(5); + List<Callable<Void>> tasks = new ArrayList<>(); + tasks.add(getInstanceOfCallable(APPLICATION_1_ID, "t1")); + tasks.add(getInstanceOfCallable(APPLICATION_1_ID, "t2")); + tasks.add(getInstanceOfCallable(APPLICATION_1_ID, "t3")); + taskExecutor.invokeAll(tasks); + + for (int i = 0; i < 50; i++) { + PropertyBean propertyBean = restClient + .getApplicationProperty(APPLICATION_1_ID, Integer.toString(i), app1AccessToken); + log.info("Retrieved metadata property: " + gson.toJson(propertyBean)); + List<String> addedValues = new ArrayList<>(Arrays.asList("t1", "t2", "t3")); + boolean hasPropertiesAdded = propertyBean.getValues().containsAll(addedValues); + Assert.assertTrue(hasPropertiesAdded, String.format("Property values have not been added for [key] %d", i)); + } + log.info("Metadata service concurrency test completed successfully"); + } + + @Test(timeOut = APPLICATION_TEST_TIMEOUT, + description = "Application startup, activation and metadata service security test", + groups = { "stratos.application.deployment" }, + priority = 3) + public void metadataSecurityTest() throws Exception { + String key = "mykey"; + String val1 = "myval1"; + + log.info("Trying to add metadata for application:" + APPLICATION_1_ID + ", with app1AccessToken: " + + app1AccessToken); + boolean hasProperty1Added = restClient.addPropertyToApplication(APPLICATION_1_ID, key, val1, app1AccessToken); + Assert.assertTrue(hasProperty1Added, "Could not add metadata property1 to application: " + APPLICATION_1_ID); + + PropertyBean propertyBean1 = restClient.getApplicationProperty(APPLICATION_1_ID, key, app1AccessToken); + log.info("Retrieved metadata property: " + gson.toJson(propertyBean1)); + Assert.assertTrue(propertyBean1 != null && propertyBean1.getValues().size() > 0, "Empty property list"); + + boolean hasPropertiesAdded1 = propertyBean1.getValues().contains(val1); + Assert.assertTrue(hasPropertiesAdded1, "Metadata properties retrieved are not correct"); + + log.info("Trying to access metadata with an empty access token. This should fail"); + propertyBean1 = restClient.getApplicationProperty(APPLICATION_1_ID, key, ""); + log.info("Retrieved metadata property: " + gson.toJson(propertyBean1)); + Assert.assertNull(propertyBean1, "Metadata service returned value for an empty access token"); + + log.info("Trying to access metadata with an access token of another app. This should fail"); + propertyBean1 = restClient.getApplicationProperty(APPLICATION_1_ID, key, app2AccessToken); + log.info("Retrieved metadata property: " + gson.toJson(propertyBean1)); + Assert.assertNull(propertyBean1, "Metadata service returned value for an access token of another application"); + + log.info("Metadata service security test completed successfully"); + } + + @Test(timeOut = APPLICATION_TEST_TIMEOUT, + description = "Application startup, activation and metadata service concurrency test", + groups = { "stratos.application.deployment" }, + priority = 10) + public void cleanupAfterUndeployingAppTest() throws Exception { + // undeploy the app and check whether metadata entries are cleared + log.info("Un-deploying the application [application id] " + APPLICATION_1_ID); + String resourcePathUndeploy = RestConstants.APPLICATIONS + "/" + APPLICATION_1_ID + + RestConstants.APPLICATIONS_UNDEPLOY; + + boolean unDeployed = restClient.undeployEntity(resourcePathUndeploy, RestConstants.APPLICATIONS_NAME); + assertTrue(unDeployed); + + boolean undeploy = topologyHandler.assertApplicationUndeploy(APPLICATION_1_ID); + if (!undeploy) { + //Need to forcefully undeploy the application + log.info("Force undeployment is going to start for the [application] " + APPLICATION_1_ID); + + restClient.undeployEntity(RestConstants.APPLICATIONS + "/" + APPLICATION_1_ID + + RestConstants.APPLICATIONS_UNDEPLOY + "?force=true", RestConstants.APPLICATIONS); + + boolean forceUndeployed = topologyHandler.assertApplicationUndeploy(APPLICATION_1_ID); + assertTrue(String.format("Forceful undeployment failed for the application %s", APPLICATION_1_ID), + forceUndeployed); + } + + for (int i = 0; i < 50; i++) { + PropertyBean propertyBeanCleaned = restClient + .getApplicationProperty(APPLICATION_1_ID, Integer.toString(i), app1AccessToken); + log.info("Retrieved metadata property: " + gson.toJson(propertyBeanCleaned)); + Assert.assertNull(propertyBeanCleaned, "Metadata properties have not been cleaned properly"); + } + log.info("Metadata service cleanup test completed successfully"); + } + + private Callable<Void> getInstanceOfCallable(final String appId, final String propertyValue) { + return new Callable<Void>() { + @Override + public Void call() throws Exception { + for (int i = 0; i < 50; i++) { + restClient.addPropertyToApplication(appId, Integer.toString(i), propertyValue, app1AccessToken); + } + return null; + } + }; + } + + @AfterTest(timeOut = APPLICATION_TEST_TIMEOUT, + groups = { "stratos.application.deployment" }) + public void cleanup() throws Exception { + // remove app-1 + log.info("Removing the application [application id] " + APPLICATION_1_ID); + boolean removedApp = restClient + .removeEntity(RestConstants.APPLICATIONS, APPLICATION_1_ID, RestConstants.APPLICATIONS_NAME); + assertTrue(removedApp); + + ApplicationBean beanRemoved = (ApplicationBean) restClient + .getEntity(RestConstants.APPLICATIONS, APPLICATION_1_ID, ApplicationBean.class, + RestConstants.APPLICATIONS_NAME); + assertNull(beanRemoved); + + // undeploy and remove app-2 + log.info("Un-deploying the application [application id] " + APPLICATION_2_ID); + String resourcePathUndeploy = RestConstants.APPLICATIONS + "/" + APPLICATION_2_ID + + RestConstants.APPLICATIONS_UNDEPLOY; + + boolean unDeployed = restClient.undeployEntity(resourcePathUndeploy, RestConstants.APPLICATIONS_NAME); + assertTrue(unDeployed); + + boolean undeploy = topologyHandler.assertApplicationUndeploy(APPLICATION_2_ID); + if (!undeploy) { + //Need to forcefully undeploy the application + log.info("Force undeployment is going to start for the [application] " + APPLICATION_2_ID); + + restClient.undeployEntity(RestConstants.APPLICATIONS + "/" + APPLICATION_2_ID + + RestConstants.APPLICATIONS_UNDEPLOY + "?force=true", RestConstants.APPLICATIONS); + + boolean forceUndeployed = topologyHandler.assertApplicationUndeploy(APPLICATION_2_ID); + assertTrue(String.format("Forceful undeployment failed for the application %s", APPLICATION_2_ID), + forceUndeployed); + } + + log.info("Removing the application [application id] " + APPLICATION_2_ID); + removedApp = restClient + .removeEntity(RestConstants.APPLICATIONS, APPLICATION_2_ID, RestConstants.APPLICATIONS_NAME); + assertTrue(removedApp); + + beanRemoved = (ApplicationBean) restClient + .getEntity(RestConstants.APPLICATIONS, APPLICATION_2_ID, ApplicationBean.class, + RestConstants.APPLICATIONS_NAME); + assertNull(beanRemoved); + + log.info("Removing the application policy [application policy id] " + APPLICATION_POLICY_ID); + boolean removeAppPolicy = restClient.removeEntity(RestConstants.APPLICATION_POLICIES, APPLICATION_POLICY_ID, + RestConstants.APPLICATION_POLICIES_NAME); + assertTrue(removeAppPolicy); + + log.info("Removing the cartridge [cartridge type] " + CARTRIDGE_TYPE); + boolean removedC1 = restClient + .removeEntity(RestConstants.CARTRIDGES, CARTRIDGE_TYPE, RestConstants.CARTRIDGES_NAME); + assertTrue(removedC1); + + log.info("Removing the autoscaling policy [autoscaling policy id] " + AUTOSCALE_POLICY_ID); + boolean removedAuto = restClient.removeEntity(RestConstants.AUTOSCALING_POLICIES, AUTOSCALE_POLICY_ID, + RestConstants.AUTOSCALING_POLICIES_NAME); + assertTrue(removedAuto); + + log.info("Removing the deployment policy [deployment policy id] " + DEPLOYMENT_POLICY_ID); + boolean removedDep = restClient.removeEntity(RestConstants.DEPLOYMENT_POLICIES, DEPLOYMENT_POLICY_ID, + RestConstants.DEPLOYMENT_POLICIES_NAME); + assertTrue(removedDep); + + log.info("Removing the network partition [network partition id] " + NETWORK_PARTITION_ID); + boolean removedNet = restClient.removeEntity(RestConstants.NETWORK_PARTITIONS, NETWORK_PARTITION_ID, + RestConstants.NETWORK_PARTITIONS_NAME); + assertTrue(removedNet); + long duration = System.currentTimeMillis() - startTime; + log.info("Metadata test completed in " + duration + " ms"); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/products/stratos/modules/integration/test-integration/src/test/java/org/apache/stratos/integration/tests/application/SampleApplicationStartupTestCase.java ---------------------------------------------------------------------- diff --git a/products/stratos/modules/integration/test-integration/src/test/java/org/apache/stratos/integration/tests/application/SampleApplicationStartupTestCase.java b/products/stratos/modules/integration/test-integration/src/test/java/org/apache/stratos/integration/tests/application/SampleApplicationStartupTestCase.java index 1890287..e0c9a23 100644 --- a/products/stratos/modules/integration/test-integration/src/test/java/org/apache/stratos/integration/tests/application/SampleApplicationStartupTestCase.java +++ b/products/stratos/modules/integration/test-integration/src/test/java/org/apache/stratos/integration/tests/application/SampleApplicationStartupTestCase.java @@ -21,7 +21,6 @@ package org.apache.stratos.integration.tests.application; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import org.apache.commons.lang.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.stratos.common.beans.application.ApplicationBean; @@ -36,13 +35,9 @@ import org.apache.stratos.mock.iaas.domain.MockInstanceMetadata; import org.testng.Assert; import org.testng.annotations.Test; -import java.util.List; -import java.util.Map; -import java.util.Properties; +import java.util.*; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; +import static org.testng.Assert.*; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertTrue; @@ -189,9 +184,9 @@ public class SampleApplicationStartupTestCase extends StratosIntegrationTest { PropertyBean propertyBean = restClient.getApplicationProperty(appId, key, accessToken); log.info("Retrieved metadata property: " + gson.toJson(propertyBean)); - Assert.assertTrue(propertyBean != null && propertyBean.getValues().length > 0, "Empty property list"); - boolean hasPropertiesAdded = ArrayUtils.contains(propertyBean.getValues(), val1) && ArrayUtils - .contains(propertyBean.getValues(), val2); + Assert.assertTrue(propertyBean != null && propertyBean.getValues().size() > 0, "Empty property list"); + List<String> addedValues = new ArrayList<>(Arrays.asList(val1, val2)); + boolean hasPropertiesAdded = propertyBean.getValues().containsAll(addedValues); Assert.assertTrue(hasPropertiesAdded, "Metadata properties retrieved are not correct"); log.info("Metadata test completed successfully"); http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/application-policies/application-policy-metadata-service-test.json ---------------------------------------------------------------------- diff --git a/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/application-policies/application-policy-metadata-service-test.json b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/application-policies/application-policy-metadata-service-test.json new file mode 100644 index 0000000..7c542e0 --- /dev/null +++ b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/application-policies/application-policy-metadata-service-test.json @@ -0,0 +1,17 @@ +{ + "id": "application-policy-metadata-service-test", + "algorithm": "one-after-another", + "networkPartitions": [ + "network-partition-metadata-service-test" + ], + "properties": [ + { + "name": "networkPartitionGroups", + "value": "network-partition-metadata-service-test" + }, + { + "name": "key-2", + "value": "value-2" + } + ] +} http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/applications/application-metadata-service-test-1.json ---------------------------------------------------------------------- diff --git a/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/applications/application-metadata-service-test-1.json b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/applications/application-metadata-service-test-1.json new file mode 100644 index 0000000..611fecf --- /dev/null +++ b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/applications/application-metadata-service-test-1.json @@ -0,0 +1,24 @@ +{ + "alias": "application-metadata-service-test-1", + "applicationId": "application-metadata-service-test-1", + "components": { + "cartridges": [ + { + "type": "c1-application-metadata-service-test", + "cartridgeMin": 3, + "cartridgeMax": 3, + "subscribableInfo": { + "alias": "c1-1x0-metadata-service-test", + "autoscalingPolicy": "autoscaling-policy-metadata-service-test", + "deploymentPolicy": "deployment-policy-metadata-service-test", + "artifactRepository": { + "privateRepo": false, + "repoUrl": "https://github.com/lakwarus/single-cartridge.git", + "repoUsername": "", + "repoPassword": "" + } + } + } + ] + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/applications/application-metadata-service-test-2.json ---------------------------------------------------------------------- diff --git a/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/applications/application-metadata-service-test-2.json b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/applications/application-metadata-service-test-2.json new file mode 100644 index 0000000..661f023 --- /dev/null +++ b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/applications/application-metadata-service-test-2.json @@ -0,0 +1,24 @@ +{ + "alias": "application-metadata-service-test-2", + "applicationId": "application-metadata-service-test-2", + "components": { + "cartridges": [ + { + "type": "c1-application-metadata-service-test", + "cartridgeMin": 1, + "cartridgeMax": 1, + "subscribableInfo": { + "alias": "c1-1x0-metadata-service-test", + "autoscalingPolicy": "autoscaling-policy-metadata-service-test", + "deploymentPolicy": "deployment-policy-metadata-service-test", + "artifactRepository": { + "privateRepo": false, + "repoUrl": "https://github.com/lakwarus/single-cartridge.git", + "repoUsername": "", + "repoPassword": "" + } + } + } + ] + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/autoscaling-policies/autoscaling-policy-metadata-service-test.json ---------------------------------------------------------------------- diff --git a/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/autoscaling-policies/autoscaling-policy-metadata-service-test.json b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/autoscaling-policies/autoscaling-policy-metadata-service-test.json new file mode 100644 index 0000000..45f742f --- /dev/null +++ b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/autoscaling-policies/autoscaling-policy-metadata-service-test.json @@ -0,0 +1,14 @@ +{ + "id": "autoscaling-policy-metadata-service-test", + "loadThresholds": { + "requestsInFlight": { + "threshold": 35 + }, + "memoryConsumption": { + "threshold": 45 + }, + "loadAverage": { + "threshold": 25 + } + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/cartridges/mock/c1-application-metadata-service-test.json ---------------------------------------------------------------------- diff --git a/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/cartridges/mock/c1-application-metadata-service-test.json b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/cartridges/mock/c1-application-metadata-service-test.json new file mode 100755 index 0000000..8a513a1 --- /dev/null +++ b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/cartridges/mock/c1-application-metadata-service-test.json @@ -0,0 +1,45 @@ +{ + "type": "c1-application-metadata-service-test", + "provider": "apache", + "host": "stratos.apache.org", + "category": "data", + "displayName": "c1-sample-application-startup-test", + "description": "c1-sample-application-startup-test Cartridge", + "version": "7", + "multiTenant": "false", + "portMapping": [ + { + "name": "http-22", + "protocol": "http", + "port": "22", + "proxyPort": "8280" + } + ], + "deployment": { + }, + "iaasProvider": [ + { + "type": "mock", + "imageId": "RegionOne/b4ca55e3-58ab-4937-82ce-817ebd10240e", + "networkInterfaces": [ + { + "networkUuid": "b55f009a-1cc6-4b17-924f-4ae0ee18db5e" + } + ], + "property": [ + { + "name": "instanceType", + "value": "RegionOne/aa5f45a2-c6d6-419d-917a-9dd2e3888594" + }, + { + "name": "keyPair", + "value": "mock-key" + }, + { + "name": "securityGroups", + "value": "default" + } + ] + } + ] +} http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/deployment-policies/deployment-policy-metadata-service-test.json ---------------------------------------------------------------------- diff --git a/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/deployment-policies/deployment-policy-metadata-service-test.json b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/deployment-policies/deployment-policy-metadata-service-test.json new file mode 100644 index 0000000..e397037 --- /dev/null +++ b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/deployment-policies/deployment-policy-metadata-service-test.json @@ -0,0 +1,18 @@ +{ + "id": "deployment-policy-metadata-service-test", + "networkPartitions": [ + { + "id": "network-partition-metadata-service-test", + "partitionAlgo": "one-after-another", + "partitions": [ + { + "id": "partition-1", + "partitionMax": 20 + } + ] + } + ] +} + + + http://git-wip-us.apache.org/repos/asf/stratos/blob/35cadf67/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/network-partitions/mock/network-partition-metadata-service-test.json ---------------------------------------------------------------------- diff --git a/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/network-partitions/mock/network-partition-metadata-service-test.json b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/network-partitions/mock/network-partition-metadata-service-test.json new file mode 100644 index 0000000..c9dd156 --- /dev/null +++ b/products/stratos/modules/integration/test-integration/src/test/resources/metadata-service-test/network-partitions/mock/network-partition-metadata-service-test.json @@ -0,0 +1,15 @@ +{ + "id": "network-partition-metadata-service-test", + "provider": "mock", + "partitions": [ + { + "id": "partition-1", + "property": [ + { + "name": "region", + "value": "default" + } + ] + } + ] +}
