/*******************************************************************************
* Copyright (c) 2015 Red Hat, Inc. Distributed under license by Red Hat, Inc.
* All rights reserved. This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors: Red Hat, Inc.
******************************************************************************/
package com.openshift.internal.restclient.model.v1;
import static com.openshift.internal.util.JBossDmrExtentions.getPath;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.MapAssert.*;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.jboss.dmr.ModelNode;
import org.json.JSONException;
import org.junit.Before;
import org.junit.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import com.openshift.internal.restclient.model.ModelNodeBuilder;
import com.openshift.internal.restclient.model.ReplicationController;
import com.openshift.internal.restclient.model.properties.ResourcePropertiesRegistry;
import com.openshift.internal.restclient.model.volume.EmptyDirVolumeSource;
import com.openshift.internal.restclient.model.volume.SecretVolumeSource;
import com.openshift.restclient.IClient;
import com.openshift.restclient.ResourceKind;
import com.openshift.restclient.images.DockerImageURI;
import com.openshift.restclient.model.IConfigMapKeySelector;
import com.openshift.restclient.model.IContainer;
import com.openshift.restclient.model.IEnvironmentVariable;
import com.openshift.restclient.model.IEnvironmentVariable.IEnvVarSource;
import com.openshift.restclient.model.IObjectFieldSelector;
import com.openshift.restclient.model.IPort;
import com.openshift.restclient.model.IReplicationController;
import com.openshift.restclient.model.ISecretKeySelector;
import com.openshift.restclient.model.volume.IVolume;
import com.openshift.restclient.model.volume.IVolumeMount;
import com.openshift.restclient.model.volume.IVolumeSource;
import com.openshift.restclient.utils.Samples;
/**
* @author Jeff Cantrill
*/
public class ReplicationControllerTest {
private static final String VERSION = "v1";
private static IReplicationController rc;
private static ModelNode node;
private static IClient client;
@Before
public void setup(){
client = mock(IClient.class);
node = ModelNode.fromJSONString(Samples.V1_REPLICATION_CONTROLLER.getContentAsString());
rc = new ReplicationController(node, client, ResourcePropertiesRegistry.getInstance().get(VERSION, ResourceKind.REPLICATION_CONTROLLER));
}
public void testGetEnvironmentVariablesWithValueFrom() {
Collection<IEnvironmentVariable> envVars = rc.getEnvironmentVariables();
//fieldref
Optional<IEnvironmentVariable> envVar = envVars.stream().filter(e->"OPENSHIFT_KUBE_PING_NAMESPACE".equals(e.getName())).findFirst();
assertTrue("Exp. to find env var", envVar.isPresent());
IEnvVarSource from = envVar.get().getValueFrom();
assertTrue(from instanceof IObjectFieldSelector);
IObjectFieldSelector selector = (IObjectFieldSelector)from;
assertEquals("v1",selector.getApiVersion());
assertEquals("metadata.namespace",selector.getFieldPath());
//configmapkeyref
envVar = envVars.stream().filter(e->"OPENSHIFT_CONFIGMAP_KEY_REF".equals(e.getName())).findFirst();
assertTrue("Exp. to find env var", envVar.isPresent());
from = envVar.get().getValueFrom();
assertTrue(from instanceof IConfigMapKeySelector);
IConfigMapKeySelector configSelector = (IConfigMapKeySelector) from;
assertEquals("xyz",configSelector.getName());
assertEquals("abc123",configSelector.getKey());
//secretkeyref
envVar = envVars.stream().filter(e->"OPENSHIFT_SECRET_KEY_REF".equals(e.getName())).findFirst();
assertTrue("Exp. to find env var", envVar.isPresent());
from = envVar.get().getValueFrom();
assertTrue(from instanceof ISecretKeySelector);
ISecretKeySelector secretKeySelector = (ISecretKeySelector) from;
assertEquals("bar",secretKeySelector.getName());
assertEquals("foo",secretKeySelector.getKey());
}
@Test
public void testEnvironmentVariable() {
//add
rc.setEnvironmentVariable("foo", "bar");
Collection<IEnvironmentVariable> envVars = rc.getEnvironmentVariables();
Optional<IEnvironmentVariable> envVar = envVars.stream().filter(e->"foo".equals(e.getName())).findFirst();
assertTrue("Exp. to find env var", envVar.isPresent());
assertEquals("bar", envVar.get().getValue());
//update
int size = rc.getEnvironmentVariables().size();
rc.setEnvironmentVariable("foo", "baz");
assertEquals(size, rc.getEnvironmentVariables().size());
envVars = rc.getEnvironmentVariables();
envVar = envVars.stream().filter(e->"foo".equals(e.getName())).findFirst();
assertEquals("baz", envVar.get().getValue());
rc.removeEnvironmentVariable("foo");
assertEquals(size - 1, rc.getEnvironmentVariables().size());
}
@Test
public void testEnvironmentVariableFromMissingEnv() {
String[] path = getPath(ReplicationController.SPEC_TEMPLATE_CONTAINERS);
ModelNode containers = node.get(path);
containers.get(0).remove("env");
testEnvironmentVariable();
}
@Test
public void testEnvironmentVariableForANamedContainer() {
rc.setEnvironmentVariable("ruby-helloworld-database", "fooz", "balls");
Collection<IEnvironmentVariable> envVars = rc.getEnvironmentVariables("ruby-helloworld-database");
Optional<IEnvironmentVariable> envVar = envVars.stream().filter(e->"fooz".equals(e.getName())).findFirst();
assertTrue("Exp. to find env var", envVar.isPresent());
assertEquals("balls", envVar.get().getValue());
}
@Test
public void setReplicaSelector() {
Map<String, String> exp = new HashMap<>();
exp.put("foo", "bar");
rc.setReplicaSelector(exp);
assertEquals(exp, rc.getReplicaSelector());
}
@Test
public void setReplicaSelectorFromMissingSelector() {
String[] path = new String[]{"status"};
node.get(path).clear();
setReplicaSelector();
}
@Test
public void setReplicaSelectorWithKeyValue() {
Map<String, String> exp = new HashMap<>();
exp.put("foo", "bar");
rc.setReplicaSelector("foo","bar");
assertEquals(exp, rc.getReplicaSelector());
}
@Test
public void getReplicaSelector() {
Map<String, String> labels = new HashMap<>();
labels.put("name", "database");
labels.put("deployment", "database-1");
labels.put("deploymentconfig", "database");
assertEquals(labels, rc.getReplicaSelector());
}
@Test
public void getServiceAccountName() {
assertEquals("dbServiceAccountName", rc.getServiceAccountName());
}
@Test
public void setServiceAccountName() {
rc.setServiceAccountName("newDBServiceAccountName");
assertEquals("newDBServiceAccountName", rc.getServiceAccountName());
}
@Test
public void getDesiredReplicaCount(){
assertEquals(1, rc.getDesiredReplicaCount());
}
@Test
public void setDesiredReplicaCount(){
rc.setDesiredReplicaCount(9);
assertEquals(9, rc.getDesiredReplicaCount());
rc.setReplicas(6);
assertEquals(6, rc.getDesiredReplicaCount());
}
@Test
public void getCurrentReplicaCount(){
assertEquals(2, rc.getCurrentReplicaCount());
}
@Test
public void testGetImages(){
String [] exp = new String []{"openshift/mysql-55-centos7:latest"};
assertArrayEquals(exp , rc.getImages().toArray());
}
@Test
public void testGetContainer() {
assertNull(rc.getContainer(" "));
assertNotNull(rc.getContainer("ruby-helloworld-database"));
}
@Test
public void testGetContainers() {
Collection<IContainer> containers = rc.getContainers();
assertNotNull(containers);
assertEquals(1, containers.size());
String[] path = getPath(ReplicationController.SPEC_TEMPLATE_CONTAINERS);
node.get(path).clear();
assertNotNull(rc.getContainers());
}
@Test
public void testAddContainer() throws JSONException {
//remove containers hack
String[] path = getPath(ReplicationController.SPEC_TEMPLATE_CONTAINERS);
node.get(path).clear();
//setup
DockerImageURI uri = new DockerImageURI("aproject/an_image_name");
IPort port = mock(IPort.class);
when(port.getProtocol()).thenReturn("TCP");
when(port.getContainerPort()).thenReturn(8080);
Set<IPort> ports = new HashSet<>();
ports.add(port);
IContainer container = rc.addContainer(uri.getName(), uri, ports, new HashMap<String, String>(), Arrays.asList("/tmp"));
List<ModelNode> containers = node.get(path).asList();
assertEquals(1, containers.size());
ModelNode exp = new ModelNodeBuilder()
.set("name", uri.getName())
.set("image",uri.toString())
.add("ports", new ModelNodeBuilder()
.set("containerPort", port.getContainerPort())
.set("protocol", port.getProtocol())
)
.add("volumeMounts", new ModelNodeBuilder()
.set("name", uri.getName() +"-"+1)
.set("mountPath", "/tmp")
.set("readOnly", false)
)
.build();
JSONAssert.assertEquals(exp.toJSONString(false), container.toJSONString(), true);
Object [] sourceNames = rc.getVolumes().stream().map(IVolumeSource::getName).toArray();
Object [] contVolNames = container.getVolumes().stream().map(IVolume::getName).toArray();
assertArrayEquals(sourceNames,contVolNames);
}
@Test
public void testAddContainerAllowsContainerToBeFurtherManipulated() throws JSONException{
//remove containers hack
String[] path = getPath(ReplicationController.SPEC_TEMPLATE_CONTAINERS);
node.get(path).clear();
//setup
DockerImageURI uri = new DockerImageURI("arepo/aproject/an_image_name");
IPort port = mock(IPort.class);
when(port.getProtocol()).thenReturn("TCP");
when(port.getContainerPort()).thenReturn(8080);
Set<IPort> ports = new HashSet<>();
ports.add(port);
IVolumeMount mount = mock(IVolumeMount.class);
when(mount.getName()).thenReturn(uri.getName() +"-"+1);
when(mount.getMountPath()).thenReturn("/tmp");
when(mount.isReadOnly()).thenReturn(Boolean.FALSE);
Set<IVolumeMount> mounts = new HashSet<>();
mounts.add(mount);
IContainer container = rc.addContainer(uri.getName());
container.setImage(uri);
container.setPorts(ports);
container.setVolumeMounts(mounts);
IVolumeMount fooVolumeMount = container.addVolumeMount("foobar");
fooVolumeMount.setMountPath("/tmp2");
ModelNode exp = new ModelNodeBuilder()
.set("name", uri.getName())
.set("image",uri.toString())
.add("ports", new ModelNodeBuilder()
.set("containerPort", port.getContainerPort())
.set("protocol", port.getProtocol())
)
.add("volumeMounts", new ModelNodeBuilder()
.set("name", uri.getName() +"-"+1)
.set("mountPath", "/tmp")
.set("readOnly", false)
)
.add("volumeMounts", new ModelNodeBuilder()
.set("name", "foobar")
.set("mountPath", "/tmp2")
)
.build();
JSONAssert.assertEquals(exp.toJSONString(false), container.toJSONString(), true);
}
@Test
public void shouldReturnTemplateLabels() {
Map<String, String> labels = rc.getTemplateLabels();
assertThat(labels)
.hasSize(3)
.includes(entry("deployment", "database-1"))
.includes(entry("deploymentconfig", "database"))
.includes(entry("name", "database"));
}
@Test
public void testSetVolumes() {
IVolumeSource source = new EmptyDirVolumeSource("myvolume");
rc.setVolumes(Collections.singleton(source));
Set<IVolumeSource> volumes = rc.getVolumes();
assertEquals(1, volumes.size());
assertEquals("myvolume", volumes.iterator().next().getName());
}
@Test
public void testAddSecretVolumeToPodSpec() throws JSONException {
IVolumeMount volumeMount = new IVolumeMount() {
public String getName() { return "my-secret"; }
public String getMountPath() { return "/path/to/my/secret/"; }
public boolean isReadOnly() { return true; }
public void setName(String name) {}
public void setMountPath(String path) {}
public void setReadOnly(boolean readonly) {}
};
SecretVolumeSource source = new SecretVolumeSource(volumeMount.getName());
source.setSecretName("the-secret");
rc.addVolume(source);
Set<IVolumeSource> podSpecVolumes = rc.getVolumes();
Optional vol = podSpecVolumes.stream()
.filter(v->v.getName().equals(volumeMount.getName()))
.findFirst();
assertTrue("Expected to find secret volume in pod spec", vol.isPresent());
}
}