下面列出了io.fabric8.kubernetes.api.model.EnvVarBuilder#io.fabric8.kubernetes.api.model.VolumeMountBuilder 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private List<VolumeMount> getVolumeMounts(ResourceConfig config) {
List<VolumeConfig> volumeConfigs = config.getVolumes();
List<VolumeMount> ret = new ArrayList<>();
if (volumeConfigs != null) {
for (VolumeConfig volumeConfig : volumeConfigs) {
List<String> mounts = volumeConfig.getMounts();
if (mounts != null) {
for (String mount : mounts) {
ret.add(new VolumeMountBuilder()
.withName(volumeConfig.getName())
.withMountPath(mount)
.withReadOnly(false).build());
}
}
}
}
return ret;
}
@Test
public void alreadyExistingInitContainer(@Mocked final ProcessorConfig config) throws Exception {
new Expectations() {{
context.getConfiguration(); result = Configuration.builder().processorConfig(config).build();
}};
PodTemplateBuilder ptb = createEmptyPodTemplate();
addVolume(ptb, "VolumeA");
Container initContainer = new ContainerBuilder()
.withName(VolumePermissionEnricher.ENRICHER_NAME)
.withVolumeMounts(new VolumeMountBuilder().withName("vol-blub").withMountPath("blub").build())
.build();
ptb.editTemplate().editSpec().withInitContainers(Collections.singletonList(initContainer)).endSpec().endTemplate();
KubernetesListBuilder klb = new KubernetesListBuilder().addToPodTemplateItems(ptb.build());
VolumePermissionEnricher enricher = new VolumePermissionEnricher(context);
enricher.enrich(PlatformMode.kubernetes,klb);
List<Container> initS = ((PodTemplate) klb.build().getItems().get(0)).getTemplate().getSpec().getInitContainers();
assertNotNull(initS);
assertEquals(1, initS.size());
Container actualInitContainer = initS.get(0);
assertEquals("blub", actualInitContainer.getVolumeMounts().get(0).getMountPath());
}
/**
* For StatefulSets, create an init container to parse ${HOSTNAME} to get the `instance.index` and write it to
* config/application.properties on a shared volume so the main container has it. Using the legacy annotation
* configuration since the current client version does not directly support InitContainers.
*
* Since 1.8 the annotation method has been removed, and the initContainer API is supported since 1.6
*
* @param imageName the image name to use in the init container
* @return a container definition with the above mentioned configuration
*/
private Container createStatefulSetInitContainer(String imageName) {
List<String> command = new LinkedList<>();
String commandString = String
.format("%s && %s", setIndexProperty("INSTANCE_INDEX"), setIndexProperty("spring.application.index"));
command.add("sh");
command.add("-c");
command.add(commandString);
return new ContainerBuilder().withName("index-provider")
.withImage(imageName)
.withImagePullPolicy("IfNotPresent")
.withCommand(command)
.withVolumeMounts(new VolumeMountBuilder().withName("config").withMountPath("/config").build())
.build();
}
private List<VolumeMount> getExternalConfigurationVolumeMounts() {
List<VolumeMount> volumeMountList = new ArrayList<>(0);
for (ExternalConfigurationVolumeSource volume : externalVolumes) {
String name = volume.getName();
if (name != null) {
if (volume.getConfigMap() != null && volume.getSecret() != null) {
log.warn("Volume {} with external Kafka Connect configuration has to contain exactly one volume source reference to either ConfigMap or Secret", name);
} else if (volume.getConfigMap() != null || volume.getSecret() != null) {
VolumeMount volumeMount = new VolumeMountBuilder()
.withName(EXTERNAL_CONFIGURATION_VOLUME_NAME_PREFIX + name)
.withMountPath(EXTERNAL_CONFIGURATION_VOLUME_MOUNT_BASE_PATH + name)
.build();
volumeMountList.add(volumeMount);
}
}
}
return volumeMountList;
}
private void mountConfigFile(PodSpec podSpec, String gitConfigMapName, boolean addVolume) {
if (addVolume) {
podSpec
.getVolumes()
.add(
new VolumeBuilder()
.withName(CONFIG_MAP_VOLUME_NAME)
.withConfigMap(
new ConfigMapVolumeSourceBuilder().withName(gitConfigMapName).build())
.build());
}
List<Container> containers = podSpec.getContainers();
containers.forEach(
container -> {
VolumeMount volumeMount =
new VolumeMountBuilder()
.withName(CONFIG_MAP_VOLUME_NAME)
.withMountPath(GIT_CONFIG_PATH)
.withSubPath(GIT_CONFIG)
.withReadOnly(false)
.withNewReadOnly(false)
.build();
container.getVolumeMounts().add(volumeMount);
});
}
@Test(
expectedExceptions = ValidationException.class,
expectedExceptionsMessageRegExp =
"Container 'main' in pod 'pod1' contains volume mount that references missing volume 'non-existing'")
public void shouldThrowExceptionWhenContainerHasVolumeMountThatReferencesMissingPodVolume()
throws Exception {
// given
String podName = "pod1";
Pod pod = createPod("pod1", "main");
pod.getSpec()
.getContainers()
.get(0)
.getVolumeMounts()
.add(new VolumeMountBuilder().withName("non-existing").withMountPath("/tmp/data").build());
PodData podData = new PodData(pod.getSpec(), pod.getMetadata());
when(kubernetesEnvironment.getPodsData()).thenReturn(ImmutableMap.of(podName, podData));
when(kubernetesEnvironment.getMachines())
.thenReturn(ImmutableMap.of(podName + "/main", mock(InternalMachineConfig.class)));
// when
podsValidator.validate(kubernetesEnvironment);
}
@Test
public void shouldCombineAllPodMounts() {
VolumeMount vm1 = new VolumeMountBuilder().withMountPath("/host/mnt1").withName("volume-1").withReadOnly(false)
.build();
VolumeMount vm2 = new VolumeMountBuilder().withMountPath("/host/mnt2").withName("volume-2").withReadOnly(false)
.build();
VolumeMount vm3 = new VolumeMountBuilder().withMountPath("/host/mnt3").withName("volume-3").withReadOnly(false)
.build();
VolumeMount vm4 = new VolumeMountBuilder().withMountPath("/host/mnt1").withName("volume-4").withReadOnly(false)
.build();
Container container1 = containerBuilder().withName("jnlp").withVolumeMounts(vm1, vm2).build();
Pod pod1 = podBuilder().withContainers(container1).endSpec().build();
Container container2 = containerBuilder().withName("jnlp").withVolumeMounts(vm3, vm4).build();
Pod pod2 = podBuilder().withContainers(container2).endSpec().build();
Pod result = combine(pod1, pod2);
List<Container> containers = result.getSpec().getContainers();
assertEquals(1, containers.size());
assertEquals(3, containers.get(0).getVolumeMounts().size());
assertThat(containers.get(0).getVolumeMounts(), containsInAnyOrder(vm2, vm3, vm4));
}
@Test
@Issue("JENKINS-50525")
public void testBuildWithCustomWorkspaceVolume() throws Exception {
PodTemplate template = new PodTemplate();
template.setWorkspaceVolume(new EmptyDirWorkspaceVolume(true));
ContainerTemplate containerTemplate = new ContainerTemplate("name", "image");
containerTemplate.setWorkingDir("");
template.getContainers().add(containerTemplate);
setupStubs();
Pod pod = new PodTemplateBuilder(template).withSlave(slave).build();
List<Container> containers = pod.getSpec().getContainers();
assertEquals(2, containers.size());
Container container0 = containers.get(0);
Container container1 = containers.get(1);
ImmutableList<VolumeMount> volumeMounts = ImmutableList.of(new VolumeMountBuilder()
.withMountPath("/home/jenkins/agent").withName("workspace-volume").withReadOnly(false).build());
assertEquals(volumeMounts, container0.getVolumeMounts());
assertEquals(volumeMounts, container1.getVolumeMounts());
assertEquals("Memory", pod.getSpec().getVolumes().get(0).getEmptyDir().getMedium());
}
@Test
public void testBuildWithDynamicPVCWorkspaceVolume(){
PodTemplate template = new PodTemplate();
template.setWorkspaceVolume(new DynamicPVCWorkspaceVolume(
null, null,null));
ContainerTemplate containerTemplate = new ContainerTemplate("name", "image");
containerTemplate.setWorkingDir("");
template.getContainers().add(containerTemplate);
setupStubs();
Pod pod = new PodTemplateBuilder(template).withSlave(slave).build();
List<Container> containers = pod.getSpec().getContainers();
assertEquals(2, containers.size());
Container container0 = containers.get(0);
Container container1 = containers.get(1);
ImmutableList<VolumeMount> volumeMounts = ImmutableList.of(new VolumeMountBuilder()
.withMountPath("/home/jenkins/agent").withName("workspace-volume").withReadOnly(false).build());
assertEquals(volumeMounts, container0.getVolumeMounts());
assertEquals(volumeMounts, container1.getVolumeMounts());
assertNotNull(pod.getSpec().getVolumes().get(0).getPersistentVolumeClaim());
}
@Test
public void testDecoratedFlinkPodWithoutLog4jAndLogback() {
final FlinkPod resultFlinkPod = flinkConfMountDecorator.decorateFlinkPod(baseFlinkPod);
final List<KeyToPath> expectedKeyToPaths = Collections.singletonList(
new KeyToPathBuilder()
.withKey(FLINK_CONF_FILENAME)
.withPath(FLINK_CONF_FILENAME)
.build());
final List<Volume> expectedVolumes = Collections.singletonList(
new VolumeBuilder()
.withName(Constants.FLINK_CONF_VOLUME)
.withNewConfigMap()
.withName(getFlinkConfConfigMapName(CLUSTER_ID))
.withItems(expectedKeyToPaths)
.endConfigMap()
.build());
assertEquals(expectedVolumes, resultFlinkPod.getPod().getSpec().getVolumes());
final List<VolumeMount> expectedVolumeMounts = Collections.singletonList(
new VolumeMountBuilder()
.withName(Constants.FLINK_CONF_VOLUME)
.withMountPath(FLINK_CONF_DIR_IN_POD)
.build());
assertEquals(expectedVolumeMounts, resultFlinkPod.getMainContainer().getVolumeMounts());
}
/**
* Creates a Volume mount
*
* @param name Name of the Volume mount
* @param path volume mount path
* @return The Volume mount created
*/
public static VolumeMount createVolumeMount(String name, String path) {
String validName = getValidVolumeName(name);
VolumeMount volumeMount = new VolumeMountBuilder()
.withName(validName)
.withMountPath(path)
.build();
log.trace("Created volume mount {} for volume {}", volumeMount, validName);
return volumeMount;
}
private static Deployment getProxyApiAppDeploymentResource() {
return new DeploymentBuilder()
.withNewMetadata()
.withName(API_PROXY)
.addToLabels("app", API_PROXY)
.endMetadata()
.withNewSpec()
.withNewSelector()
.addToMatchLabels("app", API_PROXY)
.endSelector()
.withReplicas(1)
.withNewTemplate()
.withNewMetadata()
.addToLabels("app", API_PROXY)
.endMetadata()
.withNewSpec()
.addNewContainer()
.withName(API_PROXY)
.withImage("quay.io/enmasse/api-proxy:latest")
.withPorts(new ContainerPortBuilder().withContainerPort(8443).withName("https").withProtocol("TCP").build())
.withVolumeMounts(new VolumeMountBuilder().withMountPath("/etc/tls/private").withName("api-proxy-tls").withReadOnly(true).build())
.endContainer()
.withVolumes(Collections.singletonList(new VolumeBuilder().withName("api-proxy-tls").withSecret(new SecretVolumeSourceBuilder().withDefaultMode(420).withSecretName("api-proxy-cert").build()).build()))
.endSpec()
.endTemplate()
.endSpec()
.build();
}
private VolumeMount buildCertVolumeMount() {
return new VolumeMountBuilder()
.withName(CHE_GIT_SELF_SIGNED_VOLUME)
.withNewReadOnly(true)
.withMountPath(CERT_MOUNT_PATH)
.build();
}
private VolumeMount buildCertVolumeMount() {
return new VolumeMountBuilder()
.withName(CHE_SELF_SIGNED_CERT_VOLUME)
.withNewReadOnly(true)
.withMountPath(CERT_MOUNT_PATH)
.build();
}
private void mountSshKeySecret(String secretName, PodSpec podSpec, boolean addVolume) {
if (addVolume) {
podSpec
.getVolumes()
.add(
new VolumeBuilder()
.withName(secretName)
.withSecret(
new SecretVolumeSourceBuilder()
.withSecretName(secretName)
.withDefaultMode(0600)
.build())
.build());
}
List<Container> containers = podSpec.getContainers();
containers.forEach(
container -> {
VolumeMount volumeMount =
new VolumeMountBuilder()
.withName(secretName)
.withNewReadOnly(true)
.withReadOnly(true)
.withMountPath(SSH_PRIVATE_KEYS_PATH)
.build();
container.getVolumeMounts().add(volumeMount);
});
}
private void mountConfigFile(PodSpec podSpec, String sshConfigMapName, boolean addVolume) {
String configMapVolumeName = "ssshkeyconfigvolume";
if (addVolume) {
podSpec
.getVolumes()
.add(
new VolumeBuilder()
.withName(configMapVolumeName)
.withConfigMap(
new ConfigMapVolumeSourceBuilder().withName(sshConfigMapName).build())
.build());
}
List<Container> containers = podSpec.getContainers();
containers.forEach(
container -> {
VolumeMount volumeMount =
new VolumeMountBuilder()
.withName(configMapVolumeName)
.withMountPath(SSH_CONFIG_PATH)
.withSubPath(SSH_CONFIG)
.withReadOnly(true)
.withNewReadOnly(true)
.build();
container.getVolumeMounts().add(volumeMount);
});
}
/** Returns new instance of {@link VolumeMount} with specified name, mountPath and subPath. */
public static VolumeMount newVolumeMount(String name, String mountPath, String subPath) {
return new VolumeMountBuilder()
.withMountPath(mountPath)
.withName(name)
.withSubPath(subPath)
.build();
}
public TestContainerBuilder withVolumeMount(
String volumeName, String mountPath, String subpath) {
this.volumeMounts.add(
new VolumeMountBuilder()
.withName(volumeName)
.withMountPath(mountPath)
.withSubPath(subpath)
.build());
return this;
}
private VolumeMount getDefaultVolumeMount(@CheckForNull String workingDir) {
String wd = workingDir;
if (wd == null) {
wd = ContainerTemplate.DEFAULT_WORKING_DIR;
LOGGER.log(Level.FINE, "Container workingDir is null, defaulting to {0}", wd);
}
return new VolumeMountBuilder().withMountPath(wd).withName(WORKSPACE_VOLUME_NAME).withReadOnly(false).build();
}
public static void main(String args[]) {
String master = "https://192.168.42.193:8443/";
if (args.length == 1) {
master = args[0];
}
Config config = new ConfigBuilder().withMasterUrl(master).build();
try (final KubernetesClient client = new DefaultKubernetesClient(config)) {
String namespace = "default";
log("namespace", namespace);
Pod pod = client.pods().inNamespace(namespace).load(PodPresetExamples.class.getResourceAsStream("/pod-preset-example.yml")).get();
log("Pod created");
client.pods().inNamespace(namespace).create(pod);
PodPreset podPreset = new PodPresetBuilder()
.withNewMetadata().withName("allow-database").endMetadata()
.withNewSpec()
.withNewSelector().withMatchLabels(Collections.singletonMap("role", "frontend")).endSelector()
.withEnv(new EnvVarBuilder().withName("DB_PORT").withValue("6379").build())
.withVolumeMounts(new VolumeMountBuilder().withMountPath("/cache").withName("cache-volume").build())
.withVolumes(new VolumeBuilder().withName("cache-volume").withEmptyDir(new EmptyDirVolumeSourceBuilder().build()).build())
.endSpec()
.build();
log("Creating Pod Preset : " + podPreset.getMetadata().getName());
client.settings().podPresets().inNamespace(namespace).create(podPreset);
pod = client.pods().inNamespace(namespace).withName(pod.getMetadata().getName()).get();
log("Updated pod: ");
log(SerializationUtils.dumpAsYaml(pod));
} catch (Exception e) {
log("Exception occurred: ", e.getMessage());
e.printStackTrace();
}
}
@VisibleForTesting
static Pod createPod(WorkflowInstance workflowInstance,
RunSpec runSpec,
KubernetesSecretSpec secretSpec,
String styxEnvironment) {
final String imageWithTag = runSpec.imageName().contains(":")
? runSpec.imageName()
: runSpec.imageName() + ":latest";
final String executionId = runSpec.executionId();
final PodBuilder podBuilder = new PodBuilder()
.withNewMetadata()
.withName(executionId)
.addToAnnotations(STYX_WORKFLOW_INSTANCE_ANNOTATION, workflowInstance.toKey())
.addToAnnotations(DOCKER_TERMINATION_LOGGING_ANNOTATION,
String.valueOf(runSpec.terminationLogging()))
.endMetadata();
final PodSpecBuilder specBuilder = new PodSpecBuilder()
.withRestartPolicy("Never");
final ResourceRequirementsBuilder resourceRequirements = new ResourceRequirementsBuilder();
runSpec.memRequest().ifPresent(s -> resourceRequirements.addToRequests("memory", new Quantity(s)));
runSpec.memLimit().ifPresent(s -> resourceRequirements.addToLimits("memory", new Quantity(s)));
final ContainerBuilder mainContainerBuilder = new ContainerBuilder()
.withName(MAIN_CONTAINER_NAME)
.withImage(imageWithTag)
.withArgs(runSpec.args())
.withEnv(buildEnv(workflowInstance, runSpec, styxEnvironment))
.withResources(resourceRequirements.build());
secretSpec.serviceAccountSecret().ifPresent(serviceAccountSecret -> {
final SecretVolumeSource saVolumeSource = new SecretVolumeSourceBuilder()
.withSecretName(serviceAccountSecret)
.build();
final Volume saVolume = new VolumeBuilder()
.withName(STYX_WORKFLOW_SA_SECRET_NAME)
.withSecret(saVolumeSource)
.build();
specBuilder.addToVolumes(saVolume);
final VolumeMount saMount = new VolumeMountBuilder()
.withMountPath(STYX_WORKFLOW_SA_SECRET_MOUNT_PATH)
.withName(saVolume.getName())
.withReadOnly(true)
.build();
mainContainerBuilder.addToVolumeMounts(saMount);
mainContainerBuilder.addToEnv(envVar(STYX_WORKFLOW_SA_ENV_VARIABLE,
saMount.getMountPath() + STYX_WORKFLOW_SA_JSON_KEY));
});
secretSpec.customSecret().ifPresent(secret -> {
final SecretVolumeSource secretVolumeSource = new SecretVolumeSourceBuilder()
.withSecretName(secret.name())
.build();
final Volume secretVolume = new VolumeBuilder()
.withName(secret.name())
.withSecret(secretVolumeSource)
.build();
specBuilder.addToVolumes(secretVolume);
final VolumeMount secretMount = new VolumeMountBuilder()
.withMountPath(secret.mountPath())
.withName(secretVolume.getName())
.withReadOnly(true)
.build();
mainContainerBuilder.addToVolumeMounts(secretMount);
});
specBuilder.addToContainers(mainContainerBuilder.build());
specBuilder.addToContainers(keepaliveContainer());
podBuilder.withSpec(specBuilder.build());
return podBuilder.build();
}
private static Deployment getPostgresDeployment() {
return new DeploymentBuilder()
.withNewMetadata()
.withName(POSTGRES_APP)
.addToLabels("app", POSTGRES_APP)
.addToLabels("template", POSTGRES_APP)
.endMetadata()
.withNewSpec()
.withNewSelector()
.addToMatchLabels("app", POSTGRES_APP)
.endSelector()
.withReplicas(1)
.withNewTemplate()
.withNewMetadata()
.addToLabels("app", POSTGRES_APP)
.endMetadata()
.withNewSpec()
.addNewContainer()
.withName(POSTGRES_APP)
.withImage("postgres:10.4")
.withImagePullPolicy("IfNotPresent")
.addNewPort()
.withContainerPort(5432)
.endPort()
.withEnvFrom(new EnvFromSourceBuilder()
.withNewConfigMapRef()
.withName(POSTGRES_APP)
.endConfigMapRef()
.build())
.withVolumeMounts(new VolumeMountBuilder()
.withMountPath("/var/lib/postgresql/data/")
.withName(POSTGRES_APP).build())
.endContainer()
.addNewVolume()
.withName(POSTGRES_APP)
.withNewPersistentVolumeClaim()
.withClaimName(POSTGRES_APP)
.endPersistentVolumeClaim()
.endVolume()
.endSpec()
.endTemplate()
.endSpec()
.build();
}
private static Deployment getBrokerDeployment(String name, String user, String password) {
return new DeploymentBuilder()
.withNewMetadata()
.withName(name)
.addToLabels("app", name)
.endMetadata()
.withNewSpec()
.withNewSelector()
.addToMatchLabels("app", name)
.endSelector()
.withReplicas(1)
.withNewTemplate()
.withNewMetadata()
.addToLabels("app", name)
.endMetadata()
.withNewSpec()
.addToInitContainers(new ContainerBuilder()
.withName("artemis-init")
.withImage("quay.io/enmasse/artemis-base:2.11.0")
.withCommand("/bin/sh")
.withArgs("-c",
"/opt/apache-artemis/bin/artemis create /var/run/artemis --allow-anonymous --force --user " + user + " --password " + password + " --role admin")
.withVolumeMounts(new VolumeMountBuilder()
.withName("data")
.withMountPath("/var/run/artemis")
.build(),
new VolumeMountBuilder()
.withName(name)
.withMountPath("/etc/amq-secret-volume")
.build())
.build(),
new ContainerBuilder()
.withName("replace-broker-xml")
.withImage("quay.io/enmasse/artemis-base:2.11.0")
.withCommand("/bin/sh")
.withArgs("-c", "cp /etc/amq-secret-volume/broker.xml /var/run/artemis/etc/broker.xml")
.withVolumeMounts(new VolumeMountBuilder()
.withName("data")
.withMountPath("/var/run/artemis")
.build(),
new VolumeMountBuilder()
.withName(name)
.withMountPath("/etc/amq-secret-volume")
.build())
.build())
.addNewContainer()
.withName(name)
.withImage("quay.io/enmasse/artemis-base:2.11.0")
.withImagePullPolicy("IfNotPresent")
.withCommand("/bin/sh")
.withArgs("-c", "/var/run/artemis/bin/artemis run")
.addToPorts(new ContainerPortBuilder()
.withContainerPort(5672)
.withName("amqp")
.build(),
new ContainerPortBuilder()
.withContainerPort(5671)
.withName("amqps")
.build(),
new ContainerPortBuilder()
.withContainerPort(55671)
.withName("amqpsmutual")
.build())
.withVolumeMounts(new VolumeMountBuilder()
.withName("data")
.withMountPath("/var/run/artemis")
.build(),
new VolumeMountBuilder()
.withName(name)
.withMountPath("/etc/amq-secret-volume")
.build())
.endContainer()
.addToVolumes(new VolumeBuilder()
.withName("data")
.withNewEmptyDir()
.endEmptyDir()
.build(),
new VolumeBuilder()
.withName(name)
.withNewSecret()
.withSecretName(name)
.endSecret()
.build())
.endSpec()
.endTemplate()
.endSpec()
.build();
}
/**
* Applies secret as file into workspace containers, respecting automount attribute and optional
* devfile automount property and/or mount path override.
*
* @param env kubernetes environment with workspace containers configuration
* @param runtimeIdentity identity of current runtime
* @param secret source secret to apply
* @throws InfrastructureException on misconfigured secrets or other apply error
*/
@Override
public void applySecret(KubernetesEnvironment env, RuntimeIdentity runtimeIdentity, Secret secret)
throws InfrastructureException {
final String secretMountPath = secret.getMetadata().getAnnotations().get(ANNOTATION_MOUNT_PATH);
boolean secretAutomount =
Boolean.parseBoolean(secret.getMetadata().getAnnotations().get(ANNOTATION_AUTOMOUNT));
if (secretMountPath == null) {
throw new InfrastructureException(
format(
"Unable to mount secret '%s': It is configured to be mounted as a file but the mount path was not specified. Please define the '%s' annotation on the secret to specify it.",
secret.getMetadata().getName(), ANNOTATION_MOUNT_PATH));
}
Volume volumeFromSecret =
new VolumeBuilder()
.withName(secret.getMetadata().getName())
.withSecret(
new SecretVolumeSourceBuilder()
.withNewSecretName(secret.getMetadata().getName())
.build())
.build();
for (PodData podData : env.getPodsData().values()) {
if (!podData.getRole().equals(PodRole.DEPLOYMENT)) {
continue;
}
if (podData
.getSpec()
.getVolumes()
.stream()
.anyMatch(v -> v.getName().equals(volumeFromSecret.getName()))) {
volumeFromSecret.setName(volumeFromSecret.getName() + "_" + NameGenerator.generate("", 6));
}
podData.getSpec().getVolumes().add(volumeFromSecret);
for (Container container : podData.getSpec().getContainers()) {
Optional<ComponentImpl> component = getComponent(env, container.getName());
// skip components that explicitly disable automount
if (component.isPresent() && isComponentAutomountFalse(component.get())) {
continue;
}
// if automount disabled globally and not overridden in component
if (!secretAutomount
&& (!component.isPresent() || !isComponentAutomountTrue(component.get()))) {
continue;
}
// find path override if any
Optional<String> overridePathOptional = Optional.empty();
if (component.isPresent()) {
overridePathOptional =
getOverridenComponentPath(component.get(), secret.getMetadata().getName());
}
final String componentMountPath = overridePathOptional.orElse(secretMountPath);
container
.getVolumeMounts()
.removeIf(vm -> Paths.get(vm.getMountPath()).equals(Paths.get(componentMountPath)));
secret
.getData()
.keySet()
.forEach(
secretFile ->
container
.getVolumeMounts()
.add(
new VolumeMountBuilder()
.withName(volumeFromSecret.getName())
.withMountPath(componentMountPath + "/" + secretFile)
.withSubPath(secretFile)
.withReadOnly(true)
.build()));
}
}
}
@BeforeMethod
public void setup() throws Exception {
subpathPrefixes = new SubPathPrefixes();
k8sEnv = KubernetesEnvironment.builder().build();
pod =
newPod(POD_1_NAME)
.withContainers(
newContainer(CONTAINER_1_NAME).build(), newContainer(CONTAINER_2_NAME).build())
.build();
k8sEnv.addPod(pod);
pvc = newPVC(USER_DATA_PVC_NAME);
k8sEnv.getPersistentVolumeClaims().put(USER_DATA_PVC_NAME, pvc);
pod.getSpec()
.getInitContainers()
.add(
new ContainerBuilder()
.withName("userInitContainer")
.withVolumeMounts(
new VolumeMountBuilder()
.withName("userData")
.withSubPath("/tmp/init/userData")
.build())
.build());
pod.getSpec()
.getContainers()
.get(0)
.getVolumeMounts()
.add(new VolumeMountBuilder().withName("userData").withSubPath("/home/user/data").build());
pod.getSpec()
.getVolumes()
.add(
new VolumeBuilder()
.withName("userData")
.withPersistentVolumeClaim(
new PersistentVolumeClaimVolumeSourceBuilder()
.withClaimName(USER_DATA_PVC_NAME)
.build())
.build());
}
@Test
public void shouldReplaceVolumesWithCommon() {
// given
podData
.getSpec()
.getInitContainers()
.add(
new ContainerBuilder()
.withName("userInitContainer")
.withVolumeMounts(
new VolumeMountBuilder()
.withName("initData")
.withSubPath("/tmp/init/userData")
.build())
.build());
podData
.getSpec()
.getContainers()
.get(0)
.getVolumeMounts()
.add(new VolumeMountBuilder().withName("userData").withSubPath("/home/user/data").build());
podData
.getSpec()
.getVolumes()
.add(
new VolumeBuilder()
.withName("userData")
.withPersistentVolumeClaim(
new PersistentVolumeClaimVolumeSourceBuilder()
.withClaimName("userDataPVC")
.build())
.build());
podData
.getSpec()
.getVolumes()
.add(
new VolumeBuilder()
.withName("initData")
.withPersistentVolumeClaim(
new PersistentVolumeClaimVolumeSourceBuilder()
.withClaimName("initDataPVC")
.build())
.build());
// when
podsVolumes.replacePVCVolumesWithCommon(ImmutableMap.of("pod", podData), "commonPVC");
// then
assertEquals(podData.getSpec().getVolumes().size(), 1);
assertEquals(
podData.getSpec().getVolumes().get(0).getPersistentVolumeClaim().getClaimName(),
"commonPVC");
assertEquals(
podData.getSpec().getInitContainers().get(0).getVolumeMounts().get(0).getName(),
"commonPVC");
assertEquals(
podData.getSpec().getContainers().get(0).getVolumeMounts().get(0).getName(), "commonPVC");
}
@Test
public void shouldNotReplaceNonPVCVolumes() {
// given
podData
.getSpec()
.getInitContainers()
.add(
new ContainerBuilder()
.withName("userInitContainer")
.withVolumeMounts(new VolumeMountBuilder().withName("configMap").build())
.build());
podData
.getSpec()
.getContainers()
.get(0)
.getVolumeMounts()
.add(new VolumeMountBuilder().withName("secret").withSubPath("/home/user/data").build());
podData
.getSpec()
.getVolumes()
.add(
new VolumeBuilder()
.withName("configMap")
.withConfigMap(new ConfigMapVolumeSourceBuilder().withName("configMap").build())
.build());
podData
.getSpec()
.getVolumes()
.add(
new VolumeBuilder()
.withName("secret")
.withSecret(new SecretVolumeSourceBuilder().withSecretName("secret").build())
.build());
// when
podsVolumes.replacePVCVolumesWithCommon(ImmutableMap.of("pod", podData), "commonPVC");
// then
assertEquals(podData.getSpec().getVolumes().size(), 2);
assertNotNull(podData.getSpec().getVolumes().get(0).getConfigMap());
assertNull(podData.getSpec().getVolumes().get(0).getPersistentVolumeClaim());
assertNotNull(podData.getSpec().getVolumes().get(1).getSecret());
assertNull(podData.getSpec().getVolumes().get(1).getPersistentVolumeClaim());
assertEquals(
podData.getSpec().getInitContainers().get(0).getVolumeMounts().get(0).getName(),
"configMap");
assertEquals(
podData.getSpec().getContainers().get(0).getVolumeMounts().get(0).getName(), "secret");
}
@Test
public void testMatchingUserDefinedPVCWithCheVolume() throws Exception {
// given
k8sEnv.getPersistentVolumeClaims().put("userDataPVC", newPVC("userDataPVC"));
pod.getSpec()
.getVolumes()
.add(
new VolumeBuilder()
.withName("userData")
.withPersistentVolumeClaim(
new PersistentVolumeClaimVolumeSourceBuilder()
.withClaimName("userDataPVC")
.build())
.build());
pod.getSpec()
.getContainers()
.get(0)
.getVolumeMounts()
.add(new VolumeMountBuilder().withName("userData").withSubPath("/home/user/data").build());
k8sEnv.getMachines().values().forEach(m -> m.getVolumes().clear());
k8sEnv
.getMachines()
.get(MACHINE_2_NAME)
.getVolumes()
.put("userDataPVC", new VolumeImpl().withPath("/"));
// when
provisioner.convertCheVolumes(k8sEnv, WORKSPACE_ID);
// then
assertEquals(k8sEnv.getPersistentVolumeClaims().size(), 1);
PersistentVolumeClaim pvcForUserData =
findPvc("userDataPVC", k8sEnv.getPersistentVolumeClaims());
assertNotNull(pvcForUserData);
assertEquals("userDataPVC", pvcForUserData.getMetadata().getName());
PodSpec podSpec = k8sEnv.getPodsData().get(POD_1_NAME).getSpec();
io.fabric8.kubernetes.api.model.Volume userPodVolume = podSpec.getVolumes().get(0);
assertEquals(
userPodVolume.getPersistentVolumeClaim().getClaimName(),
pvcForUserData.getMetadata().getName());
assertEquals(
podSpec.getVolumes().get(0).getPersistentVolumeClaim().getClaimName(),
pvcForUserData.getMetadata().getName());
// check container bound to user-defined PVC
Container container1 = podSpec.getContainers().get(0);
assertEquals(container1.getVolumeMounts().size(), 1);
VolumeMount volumeMount = container1.getVolumeMounts().get(0);
assertEquals(volumeMount.getName(), userPodVolume.getName());
// check container that is bound to Che Volume via Machine configuration
Container container2 = podSpec.getContainers().get(1);
VolumeMount cheVolumeMount2 = container2.getVolumeMounts().get(0);
assertEquals(cheVolumeMount2.getName(), userPodVolume.getName());
}
private void validatePod(Pod pod, boolean fromYaml, boolean directConnection) {
assertThat(pod.getMetadata().getLabels(), hasEntry("some-label", "some-label-value"));
// check containers
Map<String, Container> containers = toContainerMap(pod);
assertEquals(2, containers.size());
assertEquals("busybox", containers.get("busybox").getImage());
assertEquals(DEFAULT_JNLP_IMAGE, containers.get("jnlp").getImage());
// check volumes and volume mounts
Map<String, Volume> volumes = pod.getSpec().getVolumes().stream()
.collect(Collectors.toMap(Volume::getName, Function.identity()));
assertEquals(3, volumes.size());
assertNotNull(volumes.get("workspace-volume"));
if (fromYaml) {
assertNotNull(volumes.get("empty-volume"));
assertNotNull(volumes.get("host-volume"));
} else {
assertNotNull(volumes.get("volume-0"));
assertNotNull(volumes.get("volume-1"));
}
List<VolumeMount> mounts = containers.get("busybox").getVolumeMounts();
List<VolumeMount> jnlpMounts = containers.get("jnlp").getVolumeMounts();
VolumeMount workspaceVolume = new VolumeMountBuilder() //
.withMountPath("/home/jenkins/agent").withName("workspace-volume").withReadOnly(false).build();
// when using yaml we don't mount all volumes, just the ones explicitly listed
if (fromYaml) {
assertThat(mounts, containsInAnyOrder(workspaceVolume, //
new VolumeMountBuilder().withMountPath("/container/data").withName("host-volume").build()));
assertThat(jnlpMounts, containsInAnyOrder(workspaceVolume));
} else {
List<Matcher<? super VolumeMount>> volumeMounts = Arrays.asList( //
equalTo(workspaceVolume), //
equalTo(new VolumeMountBuilder() //
.withMountPath("/container/data").withName("volume-0").withReadOnly(false).build()),
equalTo(new VolumeMountBuilder() //
.withMountPath("/empty/dir").withName("volume-1").withReadOnly(false).build()));
assertThat(mounts, containsInAnyOrder(volumeMounts));
assertThat(jnlpMounts, containsInAnyOrder(volumeMounts));
}
validateContainers(pod, slave, directConnection);
}
@Test
public void testPodUpdate() {
try{
server.expect().withPath("/apis/settings.k8s.io/v1alpha1/namespaces/test/podpresets/podpreset-test").andReturn(200, new PodPresetBuilder()
.withNewMetadata().withName("podpreset-test").endMetadata()
.withNewSpec()
.withNewSelector().withMatchLabels(Collections.singletonMap("app", "website")).endSelector()
.withEnv(new EnvVarBuilder()
.withName("DB_PORT")
.withValue("6379")
.build())
.withVolumeMounts(new VolumeMountBuilder()
.withMountPath("/cache")
.withName("cache-volume")
.build())
.withVolumes(
new VolumeBuilder()
.withName("cache-volume")
.withEmptyDir(new EmptyDirVolumeSourceBuilder().build())
.build())
.endSpec()
.build())
.once();
Pod pod = new PodBuilder().withNewMetadata().withName("pod").withNamespace("test").withLabels(Collections.singletonMap("app", "website")).endMetadata()
.withNewSpec()
.addToContainers(new ContainerBuilder().withName("website").withImage("nginx").withImagePullPolicy("IfNotPresent").build())
.endSpec()
.build();
server.expect().withPath("/api/v1/namespaces/test/pods/pod").andReturn(200, pod).once();
KubernetesClient client = server.getClient();
pod = client.pods().inNamespace("test").withName(pod.getMetadata().getName()).get();
assertNotNull(pod);
assertEquals("pod", pod.getMetadata().getName());
assertNotNull(pod.getSpec().getVolumes().get(0).getName());
assertEquals("cache-volume", pod.getSpec().getVolumes().get(0).getName());
PodPreset podpreset = client.settings().podPresets().withName("podpreset-test").get();
assertNotNull(pod.getSpec().getAdditionalProperties().get("DB_PORT"));
assertEquals(6379, pod.getSpec().getAdditionalProperties().get("DB_PORT"));
assertEquals("podpreset-test", podpreset.getMetadata().getName());
} catch (Exception e) {
e.printStackTrace();
}
}