Search in sources :

Example 16 with V1Volume

use of io.kubernetes.client.openapi.models.V1Volume in project heron by twitter.

the class V1Controller method createVolumeAndMountsNFSCLI.

/**
 * Generates the <code>Volume</code>s and <code>Volume Mounts</code> for <code>NFS</code>s to be
 * placed in the <code>Executor</code> and <code>Manager</code> from options on the CLI.
 * @param mapOfOpts Mapping of <code>Volume</code> option <code>key-value</code> configuration pairs.
 * @param volumes A list of <code>Volume</code> to append to.
 * @param volumeMounts A list of <code>Volume Mounts</code> to append to.
 */
@VisibleForTesting
protected void createVolumeAndMountsNFSCLI(final Map<String, Map<KubernetesConstants.VolumeConfigKeys, String>> mapOfOpts, final List<V1Volume> volumes, final List<V1VolumeMount> volumeMounts) {
    for (Map.Entry<String, Map<KubernetesConstants.VolumeConfigKeys, String>> configs : mapOfOpts.entrySet()) {
        final String volumeName = configs.getKey();
        final V1Volume volume = new V1VolumeBuilder().withName(volumeName).withNewNfs().endNfs().build();
        for (Map.Entry<KubernetesConstants.VolumeConfigKeys, String> config : configs.getValue().entrySet()) {
            switch(config.getKey()) {
                case server:
                    volume.getNfs().setServer(config.getValue());
                    break;
                case pathOnNFS:
                    volume.getNfs().setPath(config.getValue());
                    break;
                case readOnly:
                    volume.getNfs().setReadOnly(Boolean.parseBoolean(config.getValue()));
                    break;
                default:
                    break;
            }
        }
        volumes.add(volume);
        volumeMounts.add(createVolumeMountsCLI(volumeName, configs.getValue()));
    }
}
Also used : V1VolumeBuilder(io.kubernetes.client.openapi.models.V1VolumeBuilder) V1Volume(io.kubernetes.client.openapi.models.V1Volume) Map(java.util.Map) HashMap(java.util.HashMap) V1ConfigMap(io.kubernetes.client.openapi.models.V1ConfigMap) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 17 with V1Volume

use of io.kubernetes.client.openapi.models.V1Volume in project heron by twitter.

the class V1Controller method createStatefulSet.

/**
 * Creates and configures the <code>StatefulSet</code> which the topology's <code>executor</code>s will run in.
 * @param containerResource Passed down to configure the <code>executor</code> resource limits.
 * @param numberOfInstances Used to configure the execution command and ports for the <code>executor</code>.
 * @param isExecutor Flag used to configure components specific to <code>executor</code> and <code>manager</code>.
 * @return A fully configured <code>StatefulSet</code> for the topology's <code>executors</code>.
 */
private V1StatefulSet createStatefulSet(Resource containerResource, int numberOfInstances, boolean isExecutor) {
    final String topologyName = getTopologyName();
    final Config runtimeConfiguration = getRuntimeConfiguration();
    final List<V1Volume> volumes = new LinkedList<>();
    final List<V1VolumeMount> volumeMounts = new LinkedList<>();
    // Collect Persistent Volume Claim configurations from the CLI.
    final Map<String, Map<KubernetesConstants.VolumeConfigKeys, String>> configsPVC = KubernetesContext.getVolumeClaimTemplates(getConfiguration(), isExecutor);
    // Collect all Volume configurations from the CLI and generate Volumes and Volume Mounts.
    createVolumeAndMountsPersistentVolumeClaimCLI(configsPVC, volumes, volumeMounts);
    createVolumeAndMountsHostPathCLI(KubernetesContext.getVolumeHostPath(getConfiguration(), isExecutor), volumes, volumeMounts);
    createVolumeAndMountsEmptyDirCLI(KubernetesContext.getVolumeEmptyDir(getConfiguration(), isExecutor), volumes, volumeMounts);
    createVolumeAndMountsNFSCLI(KubernetesContext.getVolumeNFS(getConfiguration(), isExecutor), volumes, volumeMounts);
    final V1StatefulSet statefulSet = new V1StatefulSet();
    // Setup StatefulSet's metadata.
    final V1ObjectMeta objectMeta = new V1ObjectMeta().name(getStatefulSetName(isExecutor)).labels(getPodLabels(topologyName));
    statefulSet.setMetadata(objectMeta);
    // Create the StatefulSet Spec.
    // Reduce replica count by one for Executors and set to one for Manager.
    final int replicasCount = isExecutor ? Runtime.numContainers(runtimeConfiguration).intValue() - 1 : 1;
    final V1StatefulSetSpec statefulSetSpec = new V1StatefulSetSpec().serviceName(topologyName).replicas(replicasCount);
    // Parallel pod management tells the StatefulSet controller to launch or terminate
    // all Pods in parallel, and not to wait for Pods to become Running and Ready or completely
    // terminated prior to launching or terminating another Pod.
    statefulSetSpec.setPodManagementPolicy("Parallel");
    // Add selector match labels "app=heron" and "topology=topology-name"
    // so we know which pods to manage.
    final V1LabelSelector selector = new V1LabelSelector().matchLabels(getPodMatchLabels(topologyName));
    statefulSetSpec.setSelector(selector);
    // Create a Pod Template.
    final V1PodTemplateSpec podTemplateSpec = loadPodFromTemplate(isExecutor);
    // Set up Pod Metadata.
    final V1ObjectMeta templateMetaData = new V1ObjectMeta().labels(getPodLabels(topologyName));
    Map<String, String> annotations = new HashMap<>();
    annotations.putAll(getPodAnnotations());
    annotations.putAll(getPrometheusAnnotations());
    templateMetaData.setAnnotations(annotations);
    podTemplateSpec.setMetadata(templateMetaData);
    configurePodSpec(podTemplateSpec, containerResource, numberOfInstances, isExecutor, volumes, volumeMounts);
    statefulSetSpec.setTemplate(podTemplateSpec);
    statefulSet.setSpec(statefulSetSpec);
    statefulSetSpec.setVolumeClaimTemplates(createPersistentVolumeClaims(configsPVC));
    return statefulSet;
}
Also used : HashMap(java.util.HashMap) Config(org.apache.heron.spi.common.Config) V1ObjectMeta(io.kubernetes.client.openapi.models.V1ObjectMeta) LinkedList(java.util.LinkedList) V1VolumeMount(io.kubernetes.client.openapi.models.V1VolumeMount) V1Volume(io.kubernetes.client.openapi.models.V1Volume) V1StatefulSet(io.kubernetes.client.openapi.models.V1StatefulSet) V1StatefulSetSpec(io.kubernetes.client.openapi.models.V1StatefulSetSpec) V1PodTemplateSpec(io.kubernetes.client.openapi.models.V1PodTemplateSpec) V1LabelSelector(io.kubernetes.client.openapi.models.V1LabelSelector) Map(java.util.Map) HashMap(java.util.HashMap) V1ConfigMap(io.kubernetes.client.openapi.models.V1ConfigMap)

Example 18 with V1Volume

use of io.kubernetes.client.openapi.models.V1Volume in project heron by twitter.

the class V1Controller method createVolumeAndMountsEmptyDirCLI.

/**
 * Generates the <code>Volume</code>s and <code>Volume Mounts</code> for <code>emptyDir</code>s to be
 * placed in the <code>Executor</code> and <code>Manager</code> from options on the CLI.
 * @param mapOfOpts Mapping of <code>Volume</code> option <code>key-value</code> configuration pairs.
 * @param volumes A list of <code>Volume</code> to append to.
 * @param volumeMounts A list of <code>Volume Mounts</code> to append to.
 */
@VisibleForTesting
protected void createVolumeAndMountsEmptyDirCLI(final Map<String, Map<KubernetesConstants.VolumeConfigKeys, String>> mapOfOpts, final List<V1Volume> volumes, final List<V1VolumeMount> volumeMounts) {
    for (Map.Entry<String, Map<KubernetesConstants.VolumeConfigKeys, String>> configs : mapOfOpts.entrySet()) {
        final String volumeName = configs.getKey();
        final V1Volume volume = new V1VolumeBuilder().withName(volumeName).withNewEmptyDir().endEmptyDir().build();
        for (Map.Entry<KubernetesConstants.VolumeConfigKeys, String> config : configs.getValue().entrySet()) {
            switch(config.getKey()) {
                case medium:
                    volume.getEmptyDir().medium(config.getValue());
                    break;
                case sizeLimit:
                    volume.getEmptyDir().sizeLimit(new Quantity(config.getValue()));
                    break;
                default:
                    break;
            }
        }
        volumes.add(volume);
        volumeMounts.add(createVolumeMountsCLI(volumeName, configs.getValue()));
    }
}
Also used : V1VolumeBuilder(io.kubernetes.client.openapi.models.V1VolumeBuilder) V1Volume(io.kubernetes.client.openapi.models.V1Volume) Quantity(io.kubernetes.client.custom.Quantity) Map(java.util.Map) HashMap(java.util.HashMap) V1ConfigMap(io.kubernetes.client.openapi.models.V1ConfigMap) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 19 with V1Volume

use of io.kubernetes.client.openapi.models.V1Volume in project heron by twitter.

the class V1ControllerTest method testCreateVolumeAndMountsHostPathCLI.

@Test
public void testCreateVolumeAndMountsHostPathCLI() {
    final String volumeName = "volume-name-host-path";
    final String type = "DirectoryOrCreate";
    final String pathOnHost = "path.on.host";
    final String path = "/path/to/mount";
    final String subPath = "/sub/path/to/mount";
    // Host Path.
    final Map<String, Map<VolumeConfigKeys, String>> config = ImmutableMap.of(volumeName, new HashMap<VolumeConfigKeys, String>() {

        {
            put(VolumeConfigKeys.type, type);
            put(VolumeConfigKeys.pathOnHost, pathOnHost);
            put(VolumeConfigKeys.path, path);
            put(VolumeConfigKeys.subPath, subPath);
        }
    });
    final List<V1Volume> expectedVolumes = Collections.singletonList(new V1VolumeBuilder().withName(volumeName).withNewHostPath().withNewType(type).withNewPath(pathOnHost).endHostPath().build());
    final List<V1VolumeMount> expectedMounts = Collections.singletonList(new V1VolumeMountBuilder().withName(volumeName).withMountPath(path).withSubPath(subPath).build());
    List<V1Volume> actualVolumes = new LinkedList<>();
    List<V1VolumeMount> actualMounts = new LinkedList<>();
    v1ControllerPodTemplate.createVolumeAndMountsHostPathCLI(config, actualVolumes, actualMounts);
    Assert.assertEquals("Host Path Volume populated", expectedVolumes, actualVolumes);
    Assert.assertEquals("Host Path Volume Mount populated", expectedMounts, actualMounts);
}
Also used : V1VolumeBuilder(io.kubernetes.client.openapi.models.V1VolumeBuilder) VolumeConfigKeys(org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys) V1Volume(io.kubernetes.client.openapi.models.V1Volume) Matchers.anyString(org.mockito.Matchers.anyString) V1VolumeMountBuilder(io.kubernetes.client.openapi.models.V1VolumeMountBuilder) HashMap(java.util.HashMap) V1ConfigMap(io.kubernetes.client.openapi.models.V1ConfigMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) LinkedList(java.util.LinkedList) V1VolumeMount(io.kubernetes.client.openapi.models.V1VolumeMount) Test(org.junit.Test)

Example 20 with V1Volume

use of io.kubernetes.client.openapi.models.V1Volume in project heron by twitter.

the class V1ControllerTest method testConfigurePodWithVolumesAndMountsFromCLI.

@Test
public void testConfigurePodWithVolumesAndMountsFromCLI() {
    final String volumeNameClashing = "clashing-volume";
    final String volumeMountNameClashing = "original-volume-mount";
    V1Volume baseVolume = new V1VolumeBuilder().withName(volumeNameClashing).withNewPersistentVolumeClaim().withClaimName("Original Base Claim Name").endPersistentVolumeClaim().build();
    V1VolumeMount baseVolumeMount = new V1VolumeMountBuilder().withName(volumeMountNameClashing).withMountPath("/original/mount/path").build();
    V1Volume clashingVolume = new V1VolumeBuilder().withName(volumeNameClashing).withNewPersistentVolumeClaim().withClaimName("Clashing Claim Replaced").endPersistentVolumeClaim().build();
    V1VolumeMount clashingVolumeMount = new V1VolumeMountBuilder().withName(volumeMountNameClashing).withMountPath("/clashing/mount/path").build();
    V1Volume secondaryVolume = new V1VolumeBuilder().withName("secondary-volume").withNewPersistentVolumeClaim().withClaimName("Original Secondary Claim Name").endPersistentVolumeClaim().build();
    V1VolumeMount secondaryVolumeMount = new V1VolumeMountBuilder().withName("secondary-volume-mount").withMountPath("/secondary/mount/path").build();
    // Test case container.
    // Input: [0] Pod Spec to modify, [1] Heron container to modify, [2] List of Volumes
    // [3] List of Volume Mounts.
    // Output: The expected <V1PodSpec> and <V1Container>.
    final List<TestTuple<Object[], Pair<V1PodSpec, V1Container>>> testCases = new LinkedList<>();
    // No Persistent Volume Claim.
    final V1PodSpec podSpecEmptyCase = new V1PodSpecBuilder().withVolumes(baseVolume).build();
    final V1Container executorEmptyCase = new V1ContainerBuilder().withVolumeMounts(baseVolumeMount).build();
    final V1PodSpec expectedEmptyPodSpec = new V1PodSpecBuilder().withVolumes(baseVolume).build();
    final V1Container expectedEmptyExecutor = new V1ContainerBuilder().withVolumeMounts(baseVolumeMount).build();
    testCases.add(new TestTuple<>("Empty", new Object[] { podSpecEmptyCase, executorEmptyCase, new LinkedList<>(), new LinkedList<>() }, new Pair<>(expectedEmptyPodSpec, expectedEmptyExecutor)));
    // Non-clashing Persistent Volume Claim.
    final V1PodSpec podSpecNoClashCase = new V1PodSpecBuilder().withVolumes(baseVolume).build();
    final V1Container executorNoClashCase = new V1ContainerBuilder().withVolumeMounts(baseVolumeMount).build();
    final V1PodSpec expectedNoClashPodSpec = new V1PodSpecBuilder().addToVolumes(baseVolume).addToVolumes(secondaryVolume).build();
    final V1Container expectedNoClashExecutor = new V1ContainerBuilder().addToVolumeMounts(baseVolumeMount).addToVolumeMounts(secondaryVolumeMount).build();
    testCases.add(new TestTuple<>("No Clash", new Object[] { podSpecNoClashCase, executorNoClashCase, Collections.singletonList(secondaryVolume), Collections.singletonList(secondaryVolumeMount) }, new Pair<>(expectedNoClashPodSpec, expectedNoClashExecutor)));
    // Clashing Persistent Volume Claim.
    final V1PodSpec podSpecClashCase = new V1PodSpecBuilder().withVolumes(baseVolume).build();
    final V1Container executorClashCase = new V1ContainerBuilder().withVolumeMounts(baseVolumeMount).build();
    final V1PodSpec expectedClashPodSpec = new V1PodSpecBuilder().addToVolumes(clashingVolume).addToVolumes(secondaryVolume).build();
    final V1Container expectedClashExecutor = new V1ContainerBuilder().addToVolumeMounts(clashingVolumeMount).addToVolumeMounts(secondaryVolumeMount).build();
    testCases.add(new TestTuple<>("Clashing", new Object[] { podSpecClashCase, executorClashCase, Arrays.asList(clashingVolume, secondaryVolume), Arrays.asList(clashingVolumeMount, secondaryVolumeMount) }, new Pair<>(expectedClashPodSpec, expectedClashExecutor)));
    // Testing loop.
    for (TestTuple<Object[], Pair<V1PodSpec, V1Container>> testCase : testCases) {
        v1ControllerWithPodTemplate.configurePodWithVolumesAndMountsFromCLI((V1PodSpec) testCase.input[0], (V1Container) testCase.input[1], (List<V1Volume>) testCase.input[2], (List<V1VolumeMount>) testCase.input[3]);
        Assert.assertEquals("Pod Specs match " + testCase.description, testCase.input[0], testCase.expected.first);
        Assert.assertEquals("Executors match " + testCase.description, testCase.input[1], testCase.expected.second);
    }
}
Also used : Matchers.anyString(org.mockito.Matchers.anyString) V1PodSpecBuilder(io.kubernetes.client.openapi.models.V1PodSpecBuilder) LinkedList(java.util.LinkedList) V1VolumeMount(io.kubernetes.client.openapi.models.V1VolumeMount) V1VolumeBuilder(io.kubernetes.client.openapi.models.V1VolumeBuilder) V1Container(io.kubernetes.client.openapi.models.V1Container) V1Volume(io.kubernetes.client.openapi.models.V1Volume) TestTuple(org.apache.heron.scheduler.kubernetes.KubernetesUtils.TestTuple) V1ContainerBuilder(io.kubernetes.client.openapi.models.V1ContainerBuilder) V1VolumeMountBuilder(io.kubernetes.client.openapi.models.V1VolumeMountBuilder) V1PodSpec(io.kubernetes.client.openapi.models.V1PodSpec) Pair(org.apache.heron.common.basics.Pair) Test(org.junit.Test)

Aggregations

V1Volume (io.kubernetes.client.openapi.models.V1Volume)21 Test (org.junit.Test)10 V1ConfigMap (io.kubernetes.client.openapi.models.V1ConfigMap)9 V1VolumeBuilder (io.kubernetes.client.openapi.models.V1VolumeBuilder)9 HashMap (java.util.HashMap)9 Map (java.util.Map)9 Config (org.apache.heron.spi.common.Config)8 V1VolumeMount (io.kubernetes.client.openapi.models.V1VolumeMount)7 LinkedList (java.util.LinkedList)7 Matchers.anyString (org.mockito.Matchers.anyString)6 V1VolumeMountBuilder (io.kubernetes.client.openapi.models.V1VolumeMountBuilder)5 VisibleForTesting (com.google.common.annotations.VisibleForTesting)4 ImmutableMap (com.google.common.collect.ImmutableMap)4 V1Container (io.kubernetes.client.openapi.models.V1Container)4 V1PodSpec (io.kubernetes.client.openapi.models.V1PodSpec)4 VolumeConfigKeys (org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys)4 V1EmptyDirVolumeSource (io.kubernetes.client.openapi.models.V1EmptyDirVolumeSource)3 V1ObjectMeta (io.kubernetes.client.openapi.models.V1ObjectMeta)3 V1PodTemplateSpec (io.kubernetes.client.openapi.models.V1PodTemplateSpec)3 Quantity (io.kubernetes.client.custom.Quantity)2