blob: 50719e209eeb6e8ad099477b128fc2cf44b71497 [file] [log] [blame]
/*
* 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.kubernetes.client.live;
import io.fabric8.kubernetes.api.model.*;
import junit.framework.TestCase;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.stratos.kubernetes.client.KubernetesApiClient;
import org.apache.stratos.kubernetes.client.KubernetesConstants;
import org.apache.stratos.kubernetes.client.exceptions.KubernetesClientException;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Abstract live test class.
*/
public class AbstractLiveTest extends TestCase {
protected static final Log log = LogFactory.getLog(AbstractLiveTest.class);
protected static final String DEFAULT_KUBERNETES_MASTER_IP = "172.17.8.101";
protected static final int KUBERNETES_API_PORT = 8080;
protected static final String DEFAULT_DOCKER_IMAGE = "fnichol/uhttpd";
protected static final int DEFAULT_CONTAINER_PORT = 80;
protected static final int SERVICE_PORT = 30001;
protected static final int POD_ACTIVATION_WAIT_TIME = 10000; // 10 seconds
protected static final String KUBERNETES_API_ENDPOINT = "kubernetes.api.endpoint";
protected static final String MINION_PUBLIC_IPS = "minion.public.ips";
protected static final String DOCKER_IMAGE = "docker.image";
protected static final String CONTAINER_PORT = "container.port";
protected static final String TEST_SERVICE_SOCKET = "test.service.socket";
protected static final String TEST_POD_ACTIVATION = "test.pod.activation";
protected static final String PROTOCOL_TCP = "TCP";
protected KubernetesApiClient client;
protected String dockerImage;
protected String endpoint;
protected int containerPort;
protected boolean testPodActivation;
protected boolean testServiceSocket;
protected List<String> minionPublicIPs = Arrays.asList("172.17.8.102");
protected List<String> podIdList = new CopyOnWriteArrayList<String>();
protected List<String> serviceIdList = new CopyOnWriteArrayList<String>();
@BeforeClass
public void setUp() {
log.info("Setting up live test...");
endpoint = System.getProperty(KUBERNETES_API_ENDPOINT);
if (endpoint == null) {
endpoint = "http://" + DEFAULT_KUBERNETES_MASTER_IP + ":" + KUBERNETES_API_PORT;
}
log.info(KUBERNETES_API_ENDPOINT + ": " + endpoint);
client = new KubernetesApiClient(endpoint);
dockerImage = System.getProperty(DOCKER_IMAGE);
if (dockerImage == null) {
dockerImage = DEFAULT_DOCKER_IMAGE;
}
log.info(DOCKER_IMAGE + ": " + dockerImage);
String containerPortStr = System.getProperty(CONTAINER_PORT);
if (StringUtils.isNotBlank(containerPortStr)) {
containerPort = Integer.parseInt(containerPortStr);
} else {
containerPort = DEFAULT_CONTAINER_PORT;
}
log.info(CONTAINER_PORT + ": " + containerPort);
testPodActivation = false;
String testPodActivationStr = System.getProperty(TEST_POD_ACTIVATION);
if (StringUtils.isNotBlank(testPodActivationStr)) {
testPodActivation = Boolean.parseBoolean(testPodActivationStr);
}
log.info(TEST_POD_ACTIVATION + ": " + testPodActivation);
testServiceSocket = false;
String testServiceSocketStr = System.getProperty(TEST_SERVICE_SOCKET);
if (StringUtils.isNotBlank(testServiceSocketStr)) {
testServiceSocket = Boolean.parseBoolean(testServiceSocketStr);
}
log.info(TEST_SERVICE_SOCKET + ": " + testServiceSocket);
String minionPublicIPsStr = System.getProperty(MINION_PUBLIC_IPS);
if (StringUtils.isNotBlank(minionPublicIPsStr)) {
minionPublicIPs = Arrays.asList(minionPublicIPsStr.split(","));
}
log.info(MINION_PUBLIC_IPS + ": " + minionPublicIPsStr);
log.info("Kubernetes live test setup completed");
}
@AfterClass
public void tearDown() {
log.info("Cleaning kubernetes resources...");
deleteServices();
deletePods();
log.info("Kubernetes resources cleaned");
}
protected void createPod(String podId, String podName, Map<String, String> labelMap, Map<String, String>
annotations, String containerPortName, String cpu, String memory, List<String> imagePullSecrets,
String imagePullPolicy)
throws KubernetesClientException {
log.info("Creating pod: [pod] " + podId);
List<ContainerPort> ports = createPorts(containerPortName);
client.createPod(podId, podName, annotations, labelMap, dockerImage, cpu, memory, ports, null, imagePullSecrets, imagePullPolicy);
podIdList.add(podId);
sleep(2000);
Pod pod = client.getPod(podId);
assertNotNull(pod);
log.info("Pod created successfully: [pod] " + podId);
List<Container> containers = pod.getSpec().getContainers();
assertEquals(1, containers.size());
Map<String, Quantity> limits = containers.get(0).getResources().getLimits();
log.info("Verifying container resource limits...");
assertEquals(cpu, limits.get(KubernetesConstants.RESOURCE_CPU).getAmount());
assertEquals(memory, limits.get(KubernetesConstants.RESOURCE_MEMORY).getAmount());
log.info("Container resource limits verified successfully");
if (testPodActivation) {
boolean activated = false;
long startTime = System.currentTimeMillis();
while (!activated) {
if ((System.currentTimeMillis() - startTime) > POD_ACTIVATION_WAIT_TIME) {
log.info(String.format("Pod did not activate within %d seconds: [pod] %s",
POD_ACTIVATION_WAIT_TIME / 1000, podId));
break;
}
log.info("Waiting pod status to be changed to running: [pod] " + podId);
sleep(2000);
pod = client.getPod(podId);
if ((pod != null) && (pod.getStatus().getPhase().equals(KubernetesConstants.POD_STATUS_RUNNING))) {
activated = true;
log.info("Pod state changed to running: [pod]" + pod.getMetadata().getName());
}
}
assertNotNull(pod);
assertEquals(KubernetesConstants.POD_STATUS_RUNNING, pod.getStatus().getPhase());
}
}
Pod getPod(String podId) throws KubernetesClientException {
return client.getPod(podId);
}
void deletePod(String podId) throws KubernetesClientException {
log.info("Deleting pod: " + podId);
client.deletePod(podId);
podIdList.remove(podId);
sleep(1000);
assertNull(client.getPod(podId));
log.info("Pod deleted successfully: " + podId);
}
public void deletePods() {
try {
for (String podId : podIdList) {
deletePod(podId);
}
}
catch (KubernetesClientException e) {
log.error("Could not delete pods", e);
}
}
protected void createService(String serviceId, String serviceName, Map<String, String> labelMap, Map<String,
String> annotationMap, int nodePort, String serviceType, String containerPortName, int containerPort,
List<String> publicIPs)
throws KubernetesClientException, InterruptedException, IOException {
log.info("Creating service...");
client.createService(serviceId, serviceName, labelMap, annotationMap, nodePort, serviceType,
containerPortName, containerPort,
KubernetesConstants.SESSION_AFFINITY_CLIENT_IP);
serviceIdList.add(serviceId);
sleep(1000);
Service service = client.getService(serviceId);
assertNotNull(service);
log.info("Service creation successful");
}
Service getService(String serviceId) throws KubernetesClientException {
return client.getService(serviceId);
}
void deleteService(String serviceId) throws KubernetesClientException {
log.info(String.format("Deleting service: [service] %s", serviceId));
client.deleteService(serviceId);
serviceIdList.remove(serviceId);
sleep(2000);
assertNull(client.getService(serviceId));
log.info(String.format("Service deleted successfully: [service] %s", serviceId));
}
protected void deleteServices() {
try {
for (String serviceId : serviceIdList) {
deleteService(serviceId);
}
}
catch (KubernetesClientException e) {
log.error("Could not delete services", e);
}
}
protected void sleep(long time) {
try {
Thread.sleep(time);
}
catch (InterruptedException ignore) {
}
}
protected List<ContainerPort> createPorts(String containerPortName) {
List<ContainerPort> ports = new ArrayList<ContainerPort>();
ContainerPort port = new ContainerPort();
port.setName(containerPortName);
port.setContainerPort(containerPort);
port.setProtocol(PROTOCOL_TCP);
ports.add(port);
return ports;
}
}