Search in sources :

Example 6 with VolumeConfigKeys

use of org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys in project heron by twitter.

the class V1ControllerTest method testCreateVolumeMountsCLI.

@Test
public void testCreateVolumeMountsCLI() {
    final String volumeNamePVC = "volume-name-pvc";
    final String volumeNameHostPath = "volume-name-host-path";
    final String volumeNameEmptyDir = "volume-name-empty-dir";
    final String volumeNameNFS = "volume-name-nfs";
    final String value = "inserted-value";
    // Test case container.
    // Input: [0] volume name, [1] volume options
    // Output: The expected <V1VolumeMount>.
    final List<TestTuple<Pair<String, Map<VolumeConfigKeys, String>>, V1VolumeMount>> testCases = new LinkedList<>();
    // PVC.
    final Map<VolumeConfigKeys, String> configPVC = ImmutableMap.<VolumeConfigKeys, String>builder().put(VolumeConfigKeys.claimName, value).put(VolumeConfigKeys.storageClassName, value).put(VolumeConfigKeys.sizeLimit, value).put(VolumeConfigKeys.accessModes, value).put(VolumeConfigKeys.volumeMode, value).put(VolumeConfigKeys.path, value).put(VolumeConfigKeys.subPath, value).put(VolumeConfigKeys.readOnly, "true").build();
    final V1VolumeMount volumeMountPVC = new V1VolumeMountBuilder().withName(volumeNamePVC).withMountPath(value).withSubPath(value).withReadOnly(true).build();
    testCases.add(new TestTuple<>("PVC volume mount", new Pair<>(volumeNamePVC, configPVC), volumeMountPVC));
    // Host Path.
    final Map<VolumeConfigKeys, String> configHostPath = ImmutableMap.<VolumeConfigKeys, String>builder().put(VolumeConfigKeys.type, "DirectoryOrCreate").put(VolumeConfigKeys.pathOnHost, value).put(VolumeConfigKeys.path, value).put(VolumeConfigKeys.subPath, value).put(VolumeConfigKeys.readOnly, "true").build();
    final V1VolumeMount volumeMountHostPath = new V1VolumeMountBuilder().withName(volumeNameHostPath).withMountPath(value).withSubPath(value).withReadOnly(true).build();
    testCases.add(new TestTuple<>("Host Path volume mount", new Pair<>(volumeNameHostPath, configHostPath), volumeMountHostPath));
    // Empty Dir.
    final Map<VolumeConfigKeys, String> configEmptyDir = ImmutableMap.<VolumeConfigKeys, String>builder().put(VolumeConfigKeys.sizeLimit, value).put(VolumeConfigKeys.medium, "Memory").put(VolumeConfigKeys.path, value).put(VolumeConfigKeys.subPath, value).put(VolumeConfigKeys.readOnly, "true").build();
    final V1VolumeMount volumeMountEmptyDir = new V1VolumeMountBuilder().withName(volumeNameEmptyDir).withMountPath(value).withSubPath(value).withReadOnly(true).build();
    testCases.add(new TestTuple<>("Empty Dir volume mount", new Pair<>(volumeNameEmptyDir, configEmptyDir), volumeMountEmptyDir));
    // NFS.
    final Map<VolumeConfigKeys, String> configNFS = ImmutableMap.<VolumeConfigKeys, String>builder().put(VolumeConfigKeys.server, "nfs.server.address").put(VolumeConfigKeys.readOnly, "true").put(VolumeConfigKeys.pathOnNFS, value).put(VolumeConfigKeys.path, value).put(VolumeConfigKeys.subPath, value).build();
    final V1VolumeMount volumeMountNFS = new V1VolumeMountBuilder().withName(volumeNameNFS).withMountPath(value).withSubPath(value).withReadOnly(true).build();
    testCases.add(new TestTuple<>("NFS volume mount", new Pair<>(volumeNameNFS, configNFS), volumeMountNFS));
    // Test loop.
    for (TestTuple<Pair<String, Map<VolumeConfigKeys, String>>, V1VolumeMount> testCase : testCases) {
        V1VolumeMount actual = v1ControllerPodTemplate.createVolumeMountsCLI(testCase.input.first, testCase.input.second);
        Assert.assertEquals(testCase.description, testCase.expected, actual);
    }
}
Also used : VolumeConfigKeys(org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys) TestTuple(org.apache.heron.scheduler.kubernetes.KubernetesUtils.TestTuple) 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) Pair(org.apache.heron.common.basics.Pair) Test(org.junit.Test)

Example 7 with VolumeConfigKeys

use of org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys in project heron by twitter.

the class KubernetesContextTest method createVolumeConfigs.

/**
 * Generate <code>Volume</code> Configs for testing.
 * @param testCases Test case container.
 *                  Input: [0] Config, [1] Boolean to indicate Manager/Executor.
 *                  Output: [0] expectedKeys, [1] expectedOptionsKeys, [2] expectedOptionsValues.
 * @param prefix Configuration prefix key to use in lookup.
 */
private void createVolumeConfigs(List<TestTuple<Pair<Config, Boolean>, Object[]>> testCases, String prefix) {
    final String keyPattern = prefix + "%%s.%%s";
    final String keyExecutor = String.format(keyPattern, KubernetesConstants.EXECUTOR_NAME);
    final String keyManager = String.format(keyPattern, KubernetesConstants.MANAGER_NAME);
    final String volumeNameOne = "volume-name-one";
    final String volumeNameTwo = "volume-name-two";
    final String claimName = "OnDeMaNd";
    final String storageClassField = VolumeConfigKeys.storageClassName.name();
    final String pathField = VolumeConfigKeys.path.name();
    final String claimNameField = VolumeConfigKeys.claimName.name();
    final String expectedStorageClass = "expected-storage-class";
    final String expectedPath = "/path/for/volume/expected";
    // Create test cases for Executor/Manager on even/odd indices respectively.
    for (int idx = 0; idx < 2; ++idx) {
        // Manager case is default.
        boolean isExecutor = false;
        String key = keyManager;
        String description = KubernetesConstants.MANAGER_NAME;
        // Executor case.
        if (idx % 2 == 0) {
            isExecutor = true;
            key = keyExecutor;
            description = KubernetesConstants.EXECUTOR_NAME;
        }
        final String storageClassKeyOne = String.format(key, volumeNameOne, storageClassField);
        final String storageClassKeyTwo = String.format(key, volumeNameTwo, storageClassField);
        final String pathKeyOne = String.format(key, volumeNameOne, pathField);
        final String pathKeyTwo = String.format(key, volumeNameTwo, pathField);
        final String claimNameKeyOne = String.format(key, volumeNameOne, claimNameField);
        final String claimNameKeyTwo = String.format(key, volumeNameTwo, claimNameField);
        final Config configPVC = Config.newBuilder().put(pathKeyOne, expectedPath).put(pathKeyTwo, expectedPath).put(claimNameKeyOne, claimName).put(claimNameKeyTwo, claimName).put(storageClassKeyOne, expectedStorageClass).put(storageClassKeyTwo, expectedStorageClass).build();
        final List<String> expectedKeys = Arrays.asList(volumeNameOne, volumeNameTwo);
        final List<VolumeConfigKeys> expectedOptionsKeys = Arrays.asList(VolumeConfigKeys.path, VolumeConfigKeys.storageClassName, VolumeConfigKeys.claimName);
        final List<String> expectedOptionsValues = Arrays.asList(expectedPath, expectedStorageClass, claimName);
        testCases.add(new TestTuple<>(description, new Pair<>(configPVC, isExecutor), new Object[] { expectedKeys, expectedOptionsKeys, expectedOptionsValues }));
        final Config configPVCDisabled = Config.newBuilder().put(KubernetesContext.KUBERNETES_VOLUME_FROM_CLI_DISABLED, "true").put(pathKeyOne, expectedPath).put(pathKeyTwo, expectedPath).put(claimNameKeyOne, claimName).put(claimNameKeyTwo, claimName).put(storageClassKeyOne, expectedStorageClass).put(storageClassKeyTwo, expectedStorageClass).build();
        testCases.add(new TestTuple<>(description + " Disabled should not error", new Pair<>(configPVCDisabled, !isExecutor), new Object[] { new LinkedList<String>(), new LinkedList<VolumeConfigKeys>(), new LinkedList<String>() }));
    }
}
Also used : VolumeConfigKeys(org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys) Config(org.apache.heron.spi.common.Config) LinkedList(java.util.LinkedList) Pair(org.apache.heron.common.basics.Pair)

Example 8 with VolumeConfigKeys

use of org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys in project heron by twitter.

the class KubernetesContextTest method createVolumeNFS.

/**
 * Create test cases for <code>NFS</code>.
 * @param testCases Test case container.
 *                  Input: [0] Config, [1] Boolean to indicate Manager/Executor.
 *                  Output: <code>Map<String, Map<VolumeConfigKeys, String></code>
 * @param isExecutor Boolean to indicate Manager/Executor test case generation.
 */
private void createVolumeNFS(List<TestTuple<Pair<Config, Boolean>, Map<String, Map<VolumeConfigKeys, String>>>> testCases, boolean isExecutor) {
    final String volumeNameValid = "volume-name-valid";
    final String passingValue = "should-pass";
    final String processName = isExecutor ? KubernetesConstants.EXECUTOR_NAME : KubernetesConstants.MANAGER_NAME;
    final String keyPattern = String.format(KubernetesContext.KUBERNETES_VOLUME_NFS_PREFIX + "%%s.%%s", processName);
    // With readOnly.
    final Map<String, Map<VolumeConfigKeys, String>> expectedWithReadOnly = ImmutableMap.of(volumeNameValid, new HashMap<VolumeConfigKeys, String>() {

        {
            put(VolumeConfigKeys.server, "nfs-server.default.local");
            put(VolumeConfigKeys.readOnly, "true");
            put(VolumeConfigKeys.pathOnNFS, passingValue);
            put(VolumeConfigKeys.path, passingValue);
            put(VolumeConfigKeys.subPath, passingValue);
            put(VolumeConfigKeys.readOnly, passingValue);
        }
    });
    final Config configWithReadOnly = Config.newBuilder().put(String.format(keyPattern, volumeNameValid, "server"), "nfs-server.default.local").put(String.format(keyPattern, volumeNameValid, "readOnly"), "true").put(String.format(keyPattern, volumeNameValid, "pathOnNFS"), passingValue).put(String.format(keyPattern, volumeNameValid, "path"), passingValue).put(String.format(keyPattern, volumeNameValid, "subPath"), passingValue).put(String.format(keyPattern, volumeNameValid, "readOnly"), passingValue).build();
    testCases.add(new TestTuple<>(processName + ": `NFS` with `readOnly`", new Pair<>(configWithReadOnly, isExecutor), expectedWithReadOnly));
    // With readOnly.
    final Map<String, Map<VolumeConfigKeys, String>> expectedWithoutReadOnly = ImmutableMap.of(volumeNameValid, new HashMap<VolumeConfigKeys, String>() {

        {
            put(VolumeConfigKeys.server, "nfs-server.default.local");
            put(VolumeConfigKeys.pathOnNFS, passingValue);
            put(VolumeConfigKeys.path, passingValue);
            put(VolumeConfigKeys.subPath, passingValue);
            put(VolumeConfigKeys.readOnly, passingValue);
        }
    });
    final Config configWithoutReadOnly = Config.newBuilder().put(String.format(keyPattern, volumeNameValid, "server"), "nfs-server.default.local").put(String.format(keyPattern, volumeNameValid, "pathOnNFS"), passingValue).put(String.format(keyPattern, volumeNameValid, "path"), passingValue).put(String.format(keyPattern, volumeNameValid, "subPath"), passingValue).put(String.format(keyPattern, volumeNameValid, "readOnly"), passingValue).build();
    testCases.add(new TestTuple<>(processName + ": `NFS` without `readOnly`", new Pair<>(configWithoutReadOnly, isExecutor), expectedWithoutReadOnly));
    // Ignored.
    final Config configIgnored = Config.newBuilder().put(String.format(keyPattern, volumeNameValid, "server"), "nfs-server.default.local").put(String.format(keyPattern, volumeNameValid, "readOnly"), "true").put(String.format(keyPattern, volumeNameValid, "pathOnNFS"), passingValue).put(String.format(keyPattern, volumeNameValid, "path"), passingValue).put(String.format(keyPattern, volumeNameValid, "subPath"), passingValue).put(String.format(keyPattern, volumeNameValid, "readOnly"), passingValue).build();
    testCases.add(new TestTuple<>(processName + ": `NFS` ignored", new Pair<>(configIgnored, !isExecutor), new HashMap<>()));
}
Also used : VolumeConfigKeys(org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys) HashMap(java.util.HashMap) Config(org.apache.heron.spi.common.Config) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) Map(java.util.Map) Pair(org.apache.heron.common.basics.Pair)

Example 9 with VolumeConfigKeys

use of org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys in project heron by twitter.

the class KubernetesContextTest method createVolumeEmptyDir.

/**
 * Create test cases for <code>Empty Directory</code>.
 * @param testCases Test case container.
 *                  Input: [0] Config, [1] Boolean to indicate Manager/Executor.
 *                  Output: <code>Map<String, Map<VolumeConfigKeys, String></code>
 * @param isExecutor Boolean to indicate Manager/Executor test case generation.
 */
private void createVolumeEmptyDir(List<TestTuple<Pair<Config, Boolean>, Map<String, Map<VolumeConfigKeys, String>>>> testCases, boolean isExecutor) {
    final String volumeNameValid = "volume-name-valid";
    final String passingValue = "should-pass";
    final String processName = isExecutor ? KubernetesConstants.EXECUTOR_NAME : KubernetesConstants.MANAGER_NAME;
    final String keyPattern = String.format(KubernetesContext.KUBERNETES_VOLUME_EMPTYDIR_PREFIX + "%%s.%%s", processName);
    // With Medium.
    final Map<String, Map<VolumeConfigKeys, String>> expectedWithMedium = ImmutableMap.of(volumeNameValid, new HashMap<VolumeConfigKeys, String>() {

        {
            put(VolumeConfigKeys.sizeLimit, passingValue);
            put(VolumeConfigKeys.medium, "Memory");
            put(VolumeConfigKeys.path, passingValue);
            put(VolumeConfigKeys.subPath, passingValue);
            put(VolumeConfigKeys.readOnly, passingValue);
        }
    });
    final Config configWithMedium = Config.newBuilder().put(String.format(keyPattern, volumeNameValid, "sizeLimit"), passingValue).put(String.format(keyPattern, volumeNameValid, "medium"), "Memory").put(String.format(keyPattern, volumeNameValid, "path"), passingValue).put(String.format(keyPattern, volumeNameValid, "subPath"), passingValue).put(String.format(keyPattern, volumeNameValid, "readOnly"), passingValue).build();
    testCases.add(new TestTuple<>(processName + ": `emptyDir` with `medium`", new Pair<>(configWithMedium, isExecutor), expectedWithMedium));
    // With empty Medium.
    final Map<String, Map<VolumeConfigKeys, String>> expectedEmptyMedium = ImmutableMap.of(volumeNameValid, new HashMap<VolumeConfigKeys, String>() {

        {
            put(VolumeConfigKeys.sizeLimit, passingValue);
            put(VolumeConfigKeys.medium, "");
            put(VolumeConfigKeys.path, passingValue);
            put(VolumeConfigKeys.subPath, passingValue);
            put(VolumeConfigKeys.readOnly, passingValue);
        }
    });
    final Config configEmptyMedium = Config.newBuilder().put(String.format(keyPattern, volumeNameValid, "sizeLimit"), passingValue).put(String.format(keyPattern, volumeNameValid, "medium"), "").put(String.format(keyPattern, volumeNameValid, "path"), passingValue).put(String.format(keyPattern, volumeNameValid, "subPath"), passingValue).put(String.format(keyPattern, volumeNameValid, "readOnly"), passingValue).build();
    testCases.add(new TestTuple<>(processName + ": `emptyDir` with empty `medium`", new Pair<>(configEmptyMedium, isExecutor), expectedEmptyMedium));
    // Without Medium.
    final Map<String, Map<VolumeConfigKeys, String>> expectedNoMedium = ImmutableMap.of(volumeNameValid, new HashMap<VolumeConfigKeys, String>() {

        {
            put(VolumeConfigKeys.sizeLimit, passingValue);
            put(VolumeConfigKeys.path, passingValue);
            put(VolumeConfigKeys.subPath, passingValue);
            put(VolumeConfigKeys.readOnly, passingValue);
        }
    });
    final Config configNoMedium = Config.newBuilder().put(String.format(keyPattern, volumeNameValid, "sizeLimit"), passingValue).put(String.format(keyPattern, volumeNameValid, "path"), passingValue).put(String.format(keyPattern, volumeNameValid, "subPath"), passingValue).put(String.format(keyPattern, volumeNameValid, "readOnly"), passingValue).build();
    testCases.add(new TestTuple<>(processName + ": `emptyDir` without `medium`", new Pair<>(configNoMedium, isExecutor), expectedNoMedium));
    // Ignored.
    final Config configIgnored = Config.newBuilder().put(String.format(keyPattern, volumeNameValid, "sizeLimit"), passingValue).put(String.format(keyPattern, volumeNameValid, "medium"), "").put(String.format(keyPattern, volumeNameValid, "path"), passingValue).put(String.format(keyPattern, volumeNameValid, "subPath"), passingValue).put(String.format(keyPattern, volumeNameValid, "readOnly"), passingValue).build();
    testCases.add(new TestTuple<>(processName + ": `emptyDir` ignored", new Pair<>(configIgnored, !isExecutor), new HashMap<>()));
}
Also used : VolumeConfigKeys(org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys) HashMap(java.util.HashMap) Config(org.apache.heron.spi.common.Config) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) Map(java.util.Map) Pair(org.apache.heron.common.basics.Pair)

Example 10 with VolumeConfigKeys

use of org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys in project heron by twitter.

the class V1ControllerTest method testCreatePersistentVolumeClaims.

@Test
public void testCreatePersistentVolumeClaims() {
    final String topologyName = "topology-name";
    final String volumeNameOne = "volume-name-one";
    final String volumeNameTwo = "volume-name-two";
    final String volumeNameStatic = "volume-name-static";
    final String claimNameOne = "OnDemand";
    final String claimNameTwo = "claim-name-two";
    final String claimNameStatic = "OnDEmaND";
    final String storageClassName = "storage-class-name";
    final String sizeLimit = "555Gi";
    final String accessModesList = "ReadWriteOnce,ReadOnlyMany,ReadWriteMany";
    final String accessModes = "ReadOnlyMany";
    final String volumeMode = "VolumeMode";
    final String path = "/path/to/mount/";
    final String subPath = "/sub/path/to/mount/";
    final Map<String, Map<VolumeConfigKeys, String>> mapPVCOpts = ImmutableMap.of(volumeNameOne, new HashMap<VolumeConfigKeys, String>() {

        {
            put(VolumeConfigKeys.claimName, claimNameOne);
            put(VolumeConfigKeys.storageClassName, storageClassName);
            put(VolumeConfigKeys.sizeLimit, sizeLimit);
            put(VolumeConfigKeys.accessModes, accessModesList);
            put(VolumeConfigKeys.volumeMode, volumeMode);
            put(VolumeConfigKeys.path, path);
        }
    }, volumeNameTwo, new HashMap<VolumeConfigKeys, String>() {

        {
            put(VolumeConfigKeys.claimName, claimNameTwo);
            put(VolumeConfigKeys.storageClassName, storageClassName);
            put(VolumeConfigKeys.sizeLimit, sizeLimit);
            put(VolumeConfigKeys.accessModes, accessModes);
            put(VolumeConfigKeys.volumeMode, volumeMode);
            put(VolumeConfigKeys.path, path);
            put(VolumeConfigKeys.subPath, subPath);
        }
    }, volumeNameStatic, new HashMap<VolumeConfigKeys, String>() {

        {
            put(VolumeConfigKeys.claimName, claimNameStatic);
            put(VolumeConfigKeys.sizeLimit, sizeLimit);
            put(VolumeConfigKeys.accessModes, accessModes);
            put(VolumeConfigKeys.volumeMode, volumeMode);
            put(VolumeConfigKeys.path, path);
            put(VolumeConfigKeys.subPath, subPath);
        }
    });
    final V1PersistentVolumeClaim claimOne = new V1PersistentVolumeClaimBuilder().withNewMetadata().withName(volumeNameOne).withLabels(V1Controller.getPersistentVolumeClaimLabels(topologyName)).endMetadata().withNewSpec().withStorageClassName(storageClassName).withAccessModes(Arrays.asList(accessModesList.split(","))).withVolumeMode(volumeMode).withNewResources().addToRequests("storage", new Quantity(sizeLimit)).endResources().endSpec().build();
    final V1PersistentVolumeClaim claimStatic = new V1PersistentVolumeClaimBuilder().withNewMetadata().withName(volumeNameStatic).withLabels(V1Controller.getPersistentVolumeClaimLabels(topologyName)).endMetadata().withNewSpec().withStorageClassName("").withAccessModes(Collections.singletonList(accessModes)).withVolumeMode(volumeMode).withNewResources().addToRequests("storage", new Quantity(sizeLimit)).endResources().endSpec().build();
    final List<V1PersistentVolumeClaim> expectedClaims = new LinkedList<>(Arrays.asList(claimOne, claimStatic));
    final List<V1PersistentVolumeClaim> actualClaims = v1ControllerWithPodTemplate.createPersistentVolumeClaims(mapPVCOpts);
    Assert.assertTrue(expectedClaims.containsAll(actualClaims));
}
Also used : VolumeConfigKeys(org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys) V1PersistentVolumeClaim(io.kubernetes.client.openapi.models.V1PersistentVolumeClaim) Quantity(io.kubernetes.client.custom.Quantity) Matchers.anyString(org.mockito.Matchers.anyString) HashMap(java.util.HashMap) V1ConfigMap(io.kubernetes.client.openapi.models.V1ConfigMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) V1PersistentVolumeClaimBuilder(io.kubernetes.client.openapi.models.V1PersistentVolumeClaimBuilder) LinkedList(java.util.LinkedList) Test(org.junit.Test)

Aggregations

VolumeConfigKeys (org.apache.heron.scheduler.kubernetes.KubernetesConstants.VolumeConfigKeys)11 ImmutableMap (com.google.common.collect.ImmutableMap)10 HashMap (java.util.HashMap)10 Map (java.util.Map)10 LinkedList (java.util.LinkedList)7 Pair (org.apache.heron.common.basics.Pair)7 V1ConfigMap (io.kubernetes.client.openapi.models.V1ConfigMap)6 Test (org.junit.Test)6 Matchers.anyString (org.mockito.Matchers.anyString)6 V1VolumeMount (io.kubernetes.client.openapi.models.V1VolumeMount)5 V1VolumeMountBuilder (io.kubernetes.client.openapi.models.V1VolumeMountBuilder)5 Config (org.apache.heron.spi.common.Config)5 V1Volume (io.kubernetes.client.openapi.models.V1Volume)4 V1VolumeBuilder (io.kubernetes.client.openapi.models.V1VolumeBuilder)4 TestTuple (org.apache.heron.scheduler.kubernetes.KubernetesUtils.TestTuple)2 Quantity (io.kubernetes.client.custom.Quantity)1 V1PersistentVolumeClaim (io.kubernetes.client.openapi.models.V1PersistentVolumeClaim)1 V1PersistentVolumeClaimBuilder (io.kubernetes.client.openapi.models.V1PersistentVolumeClaimBuilder)1 List (java.util.List)1