use of org.apache.heron.scheduler.kubernetes.KubernetesUtils.TestTuple in project heron by twitter.
the class KubernetesContextTest method testGetVolumeConfigsErrors.
@Test
public void testGetVolumeConfigsErrors() {
final String prefix = KubernetesContext.KUBERNETES_VOLUME_CLAIM_PREFIX;
final String volumeNameValid = "volume-name-valid";
final String volumeNameInvalid = "volume-Name-Invalid";
final String passingValue = "should-pass";
final String failureValue = "Should-Fail";
final String generalFailureMessage = "Invalid Volume configuration";
final String keyPattern = String.format(KubernetesContext.KUBERNETES_VOLUME_CLAIM_PREFIX + "%%s.%%s", KubernetesConstants.EXECUTOR_NAME);
final List<TestTuple<Config, String>> testCases = new LinkedList<>();
// Invalid option key test.
final Config configInvalidOption = Config.newBuilder().put(String.format(keyPattern, volumeNameValid, "claimName"), passingValue).put(String.format(keyPattern, volumeNameValid, "storageClassName"), passingValue).put(String.format(keyPattern, volumeNameValid, "sizeLimit"), passingValue).put(String.format(keyPattern, volumeNameValid, "accessModes"), passingValue).put(String.format(keyPattern, volumeNameValid, "volumeMode"), passingValue).put(String.format(keyPattern, volumeNameValid, "path"), passingValue).put(String.format(keyPattern, volumeNameValid, "subPath"), passingValue).put(String.format(keyPattern, volumeNameValid, "server"), passingValue).put(String.format(keyPattern, volumeNameValid, "readOnly"), passingValue).put(String.format(keyPattern, volumeNameValid, "type"), passingValue).put(String.format(keyPattern, volumeNameValid, "medium"), passingValue).put(String.format(keyPattern, volumeNameValid, "NonExistentKey"), failureValue).build();
testCases.add(new TestTuple<>("Invalid option key should trigger exception", configInvalidOption, generalFailureMessage));
// Invalid Volume Name.
final Config configInvalidVolumeName = Config.newBuilder().put(String.format(keyPattern, volumeNameInvalid, "path"), failureValue).build();
testCases.add(new TestTuple<>("Invalid Volume Name should trigger exception", configInvalidVolumeName, "lowercase RFC-1123"));
// Required Path.
final Config configRequiredPath = Config.newBuilder().put(String.format(keyPattern, volumeNameValid, "claimName"), passingValue).put(String.format(keyPattern, volumeNameValid, "storageClassName"), passingValue).put(String.format(keyPattern, volumeNameValid, "sizeLimit"), passingValue).put(String.format(keyPattern, volumeNameValid, "accessModes"), passingValue).put(String.format(keyPattern, volumeNameValid, "volumeMode"), passingValue).put(String.format(keyPattern, volumeNameValid, "subPath"), passingValue).put(String.format(keyPattern, volumeNameValid, "server"), passingValue).put(String.format(keyPattern, volumeNameValid, "readOnly"), passingValue).put(String.format(keyPattern, volumeNameValid, "type"), passingValue).put(String.format(keyPattern, volumeNameValid, "medium"), passingValue).build();
testCases.add(new TestTuple<>("Missing path should trigger exception", configRequiredPath, "All Volumes require a 'path'."));
// Disabled.
final Config configDisabled = Config.newBuilder().put(KubernetesContext.KUBERNETES_VOLUME_FROM_CLI_DISABLED, "true").put(String.format(keyPattern, volumeNameValid, "claimName"), passingValue).put(String.format(keyPattern, volumeNameValid, "storageClassName"), passingValue).put(String.format(keyPattern, volumeNameValid, "sizeLimit"), passingValue).put(String.format(keyPattern, volumeNameValid, "accessModes"), passingValue).put(String.format(keyPattern, volumeNameValid, "volumeMode"), passingValue).put(String.format(keyPattern, volumeNameValid, "path"), passingValue).put(String.format(keyPattern, volumeNameValid, "subPath"), passingValue).put(String.format(keyPattern, volumeNameValid, "server"), passingValue).put(String.format(keyPattern, volumeNameValid, "readOnly"), passingValue).put(String.format(keyPattern, volumeNameValid, "type"), passingValue).put(String.format(keyPattern, volumeNameValid, "medium"), passingValue).build();
testCases.add(new TestTuple<>("Disabled functionality should trigger exception", configDisabled, "Configuring Volumes from the CLI is disabled."));
// Testing loop.
for (TestTuple<Config, String> testCase : testCases) {
String message = "";
try {
KubernetesContext.getVolumeConfigs(testCase.input, prefix, true);
} catch (TopologySubmissionException e) {
message = e.getMessage();
}
Assert.assertTrue(testCase.description, message.contains(testCase.expected));
}
}
use of org.apache.heron.scheduler.kubernetes.KubernetesUtils.TestTuple in project heron by twitter.
the class V1ControllerTest method testLoadPodFromTemplateValidConfigMap.
@Test
public void testLoadPodFromTemplateValidConfigMap() {
final String expected = " containers: [class V1Container {\n" + " args: null\n" + " command: null\n" + " env: null\n" + " envFrom: null\n" + " image: apache/heron:latest\n" + " imagePullPolicy: null\n" + " lifecycle: null\n" + " livenessProbe: null\n" + " name: heron-tracker\n" + " ports: [class V1ContainerPort {\n" + " containerPort: 8888\n" + " hostIP: null\n" + " hostPort: null\n" + " name: api-port\n" + " protocol: null\n" + " }]\n" + " readinessProbe: null\n" + " resources: class V1ResourceRequirements {\n" + " limits: {cpu=Quantity{number=0.400, format=DECIMAL_SI}, " + "memory=Quantity{number=512000000, format=DECIMAL_SI}}\n" + " requests: {cpu=Quantity{number=0.100, format=DECIMAL_SI}, " + "memory=Quantity{number=200000000, format=DECIMAL_SI}}\n" + " }\n" + " securityContext: null\n" + " startupProbe: null\n" + " stdin: null\n" + " stdinOnce: null\n" + " terminationMessagePath: null\n" + " terminationMessagePolicy: null\n" + " tty: null\n" + " volumeDevices: null\n" + " volumeMounts: null\n" + " workingDir: null\n" + " }]";
// ConfigMap with valid Pod Template.
final V1ConfigMap configMapValidPod = new V1ConfigMapBuilder().withNewMetadata().withName(CONFIGMAP_NAME).endMetadata().addToData(POD_TEMPLATE_NAME, POD_TEMPLATE_VALID).build();
// Test case container.
// Input: ConfigMap to setup mock V1Controller, Boolean flag for executor/manager switch.
// Output: The expected Pod template as a string.
final List<TestTuple<Pair<V1ConfigMap, Boolean>, String>> testCases = new LinkedList<>();
testCases.add(new TestTuple<>("Executor valid Pod Template", new Pair<>(configMapValidPod, true), expected));
testCases.add(new TestTuple<>("Manager valid Pod Template", new Pair<>(configMapValidPod, false), expected));
// Test loop.
for (TestTuple<Pair<V1ConfigMap, Boolean>, String> testCase : testCases) {
doReturn(testCase.input.first).when(v1ControllerWithPodTemplate).getConfigMap(anyString());
V1PodTemplateSpec podTemplateSpec = v1ControllerWithPodTemplate.loadPodFromTemplate(true);
Assert.assertTrue(podTemplateSpec.toString().contains(testCase.expected));
}
}
use of org.apache.heron.scheduler.kubernetes.KubernetesUtils.TestTuple in project heron by twitter.
the class V1ControllerTest method testLoadPodFromTemplateNoTargetConfigMap.
@Test
public void testLoadPodFromTemplateNoTargetConfigMap() {
final List<TestTuple<Boolean, String>> testCases = new LinkedList<>();
testCases.add(new TestTuple<>("Executor no target ConfigMap", true, "Failed to locate Pod Template"));
testCases.add(new TestTuple<>("Manager no target ConfigMap", false, "Failed to locate Pod Template"));
final V1ConfigMap configMapNoTargetData = new V1ConfigMapBuilder().withNewMetadata().withName(CONFIGMAP_NAME).endMetadata().addToData("Dummy Key", "Dummy Value").build();
for (TestTuple<Boolean, String> testCase : testCases) {
doReturn(configMapNoTargetData).when(v1ControllerWithPodTemplate).getConfigMap(anyString());
String message = "";
try {
v1ControllerWithPodTemplate.loadPodFromTemplate(testCase.input);
} catch (TopologySubmissionException e) {
message = e.getMessage();
}
Assert.assertTrue(testCase.description, message.contains(testCase.expected));
}
}
use of org.apache.heron.scheduler.kubernetes.KubernetesUtils.TestTuple in project heron by twitter.
the class V1ControllerTest method testCreatePersistentVolumeClaimVolumesAndMounts.
@Test
public void testCreatePersistentVolumeClaimVolumesAndMounts() {
final String volumeNameOne = "VolumeNameONE";
final String volumeNameTwo = "VolumeNameTWO";
final String claimNameOne = "claim-name-one";
final String claimNameTwo = "OnDemand";
final String mountPathOne = "/mount/path/ONE";
final String mountPathTwo = "/mount/path/TWO";
final String mountSubPathTwo = "/mount/sub/path/TWO";
Map<String, Map<VolumeConfigKeys, String>> mapOfOpts = ImmutableMap.of(volumeNameOne, ImmutableMap.of(VolumeConfigKeys.claimName, claimNameOne, VolumeConfigKeys.path, mountPathOne), volumeNameTwo, ImmutableMap.of(VolumeConfigKeys.claimName, claimNameTwo, VolumeConfigKeys.path, mountPathTwo, VolumeConfigKeys.subPath, mountSubPathTwo));
final V1Volume volumeOne = new V1VolumeBuilder().withName(volumeNameOne).withNewPersistentVolumeClaim().withClaimName(claimNameOne).endPersistentVolumeClaim().build();
final V1Volume volumeTwo = new V1VolumeBuilder().withName(volumeNameTwo).withNewPersistentVolumeClaim().withClaimName(claimNameTwo).endPersistentVolumeClaim().build();
final V1VolumeMount volumeMountOne = new V1VolumeMountBuilder().withName(volumeNameOne).withMountPath(mountPathOne).build();
final V1VolumeMount volumeMountTwo = new V1VolumeMountBuilder().withName(volumeNameTwo).withMountPath(mountPathTwo).withSubPath(mountSubPathTwo).build();
// Test case container.
// Input: Map of Volume configurations.
// Output: The expected lists of Volumes and Volume Mounts.
final List<TestTuple<Map<String, Map<VolumeConfigKeys, String>>, Pair<List<V1Volume>, List<V1VolumeMount>>>> testCases = new LinkedList<>();
// Default case: No PVC provided.
testCases.add(new TestTuple<>("Generated an empty list of Volumes", new HashMap<>(), new Pair<>(new LinkedList<>(), new LinkedList<>())));
// PVC Provided.
final Pair<List<V1Volume>, List<V1VolumeMount>> expectedFull = new Pair<>(new LinkedList<>(Arrays.asList(volumeOne, volumeTwo)), new LinkedList<>(Arrays.asList(volumeMountOne, volumeMountTwo)));
testCases.add(new TestTuple<>("Generated a list of Volumes", mapOfOpts, new Pair<>(expectedFull.first, expectedFull.second)));
// Testing loop.
for (TestTuple<Map<String, Map<VolumeConfigKeys, String>>, Pair<List<V1Volume>, List<V1VolumeMount>>> testCase : testCases) {
List<V1Volume> actualVolume = new LinkedList<>();
List<V1VolumeMount> actualVolumeMount = new LinkedList<>();
v1ControllerPodTemplate.createVolumeAndMountsPersistentVolumeClaimCLI(testCase.input, actualVolume, actualVolumeMount);
Assert.assertTrue(testCase.description, (testCase.expected.first).containsAll(actualVolume));
Assert.assertTrue(testCase.description + " Mounts", (testCase.expected.second).containsAll(actualVolumeMount));
}
}
use of org.apache.heron.scheduler.kubernetes.KubernetesUtils.TestTuple in project heron by twitter.
the class V1ControllerTest method testLoadPodFromTemplateInvalidConfigMap.
@Test
public void testLoadPodFromTemplateInvalidConfigMap() {
// ConfigMap with an invalid Pod Template.
final String invalidPodTemplate = "apiVersion: apps/v1\n" + "kind: InvalidTemplate\n" + "metadata:\n" + " name: heron-tracker\n" + " namespace: default\n" + "template:\n" + " metadata:\n" + " labels:\n" + " app: heron-tracker\n" + " spec:\n";
final V1ConfigMap configMap = new V1ConfigMapBuilder().withNewMetadata().withName(CONFIGMAP_NAME).endMetadata().addToData(POD_TEMPLATE_NAME, invalidPodTemplate).build();
// Test case container.
// Input: ConfigMap to setup mock V1Controller, Boolean flag for executor/manager switch.
// Output: The expected Pod template as a string.
final List<TestTuple<Pair<V1ConfigMap, Boolean>, String>> testCases = new LinkedList<>();
testCases.add(new TestTuple<>("Executor invalid Pod Template", new Pair<>(configMap, true), "Error parsing"));
testCases.add(new TestTuple<>("Manager invalid Pod Template", new Pair<>(configMap, false), "Error parsing"));
// Test loop.
for (TestTuple<Pair<V1ConfigMap, Boolean>, String> testCase : testCases) {
doReturn(testCase.input.first).when(v1ControllerWithPodTemplate).getConfigMap(anyString());
String message = "";
try {
v1ControllerWithPodTemplate.loadPodFromTemplate(testCase.input.second);
} catch (TopologySubmissionException e) {
message = e.getMessage();
}
Assert.assertTrue(message.contains(testCase.expected));
}
}
Aggregations