Skip to content

Commit

Permalink
Check volume requirement on all containers. (#470)
Browse files Browse the repository at this point in the history
* Check volume requirement on all containers.
* Added volumes and additional containers to test that both are mapped.
* Moved comment. Added negative test where one volume mount is absent.

Fixes #454
  • Loading branch information
corneil authored Aug 27, 2024
1 parent 6533b2f commit 65dbb7d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.springframework.cloud.deployer.spi.kubernetes;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -249,11 +250,6 @@ PodSpec createPodSpec(AppDeploymentRequest appDeploymentRequest) {

podSpec.withTolerations(this.deploymentPropertiesResolver.getTolerations(deploymentProperties));

// only add volumes with corresponding volume mounts
podSpec.withVolumes(this.deploymentPropertiesResolver.getVolumes(deploymentProperties).stream()
.filter(volume -> container.getVolumeMounts().stream()
.anyMatch(volumeMount -> volumeMount.getName().equals(volume.getName())))
.collect(Collectors.toList()));

if (hostNetwork) {
podSpec.withHostNetwork(true);
Expand Down Expand Up @@ -311,6 +307,22 @@ PodSpec createPodSpec(AppDeploymentRequest appDeploymentRequest) {
.forEach((c) -> c.setSecurityContext(containerSecurityContext));
}
podSpec.addAllToContainers(additionalContainers);

List<Container> allContainers = new ArrayList<>();
allContainers.add(container);
if (initContainer != null) {
allContainers.add(initContainer);
}
allContainers.addAll(additionalContainers);
// only add volumes with corresponding volume mounts in any container.
podSpec.withVolumes(this.deploymentPropertiesResolver.getVolumes(deploymentProperties).stream()
.filter(volume -> allContainers.stream()
.anyMatch(c -> c.getVolumeMounts()
.stream()
.anyMatch(volumeMount -> volumeMount.getName().equals(volume.getName()))
)
)
.collect(Collectors.toList()));
return podSpec.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,19 @@
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

import io.fabric8.kubernetes.api.model.AffinityBuilder;
import io.fabric8.kubernetes.api.model.Capabilities;
import io.fabric8.kubernetes.api.model.ConfigMapKeySelector;
import io.fabric8.kubernetes.api.model.ConfigMapVolumeSource;
import io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceBuilder;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.EnvVar;
import io.fabric8.kubernetes.api.model.HostPathVolumeSource;
import io.fabric8.kubernetes.api.model.HostPathVolumeSourceBuilder;
import io.fabric8.kubernetes.api.model.KeyToPath;
import io.fabric8.kubernetes.api.model.LabelSelector;
import io.fabric8.kubernetes.api.model.LabelSelectorRequirementBuilder;
import io.fabric8.kubernetes.api.model.NodeAffinity;
Expand All @@ -50,6 +55,7 @@
import io.fabric8.kubernetes.api.model.SecurityContextBuilder;
import io.fabric8.kubernetes.api.model.Sysctl;
import io.fabric8.kubernetes.api.model.Toleration;
import io.fabric8.kubernetes.api.model.Volume;
import io.fabric8.kubernetes.api.model.VolumeBuilder;
import io.fabric8.kubernetes.api.model.WeightedPodAffinityTerm;
import io.fabric8.kubernetes.api.model.WindowsSecurityContextOptions;
Expand Down Expand Up @@ -139,7 +145,47 @@ public void deployWithVolumesAndVolumeMounts() throws Exception {
new VolumeBuilder().withName("testpvc").withNewPersistentVolumeClaim("testClaim", true).build(),
new VolumeBuilder().withName("testnfs").withNewNfs("/test/override/nfs", null, "192.168.1.1:111").build());
}
@Test
public void deployWithVolumesAndVolumeMountsOnAdditionalContainer() throws Exception {
AppDefinition definition = new AppDefinition("app-test", null);
Map<String, String> props = new HashMap<>();
props.put("spring.cloud.deployer.kubernetes.volumes", "[{name: 'config', configMap: {name: promtail-config, items: [{key: promtail.yaml, path: promtail.yaml}]}},{name: 'config2', configMap: {name: promtail-config, items: [{key: promtail.yaml, path: promtail.yaml}]}}]");
props.put("spring.cloud.deployer.kubernetes.additional-containers", "[{name: 'promtail',image: image-path-of-promtail, ports:[{protocol: TCP,containerPort: 8080}],args: [\"-config.file=/home/conf/promtail.yaml\"],volumeMounts: [{name: 'config', mountPath: '/home/conf'}]},{name: 'promtail2',image: image-path-of-promtail, ports:[{protocol: TCP,containerPort: 8080}],args: [\"-config.file=/home/conf/promtail.yaml\"],volumeMounts: [{name: 'config2', mountPath: '/home/conf'}]}]");
AppDeploymentRequest appDeploymentRequest = new AppDeploymentRequest(definition, getResource(), props);

deployer = k8sAppDeployer();
PodSpec podSpec = deployer.createPodSpec(appDeploymentRequest);

ConfigMapVolumeSource configMapVolumeSource = new ConfigMapVolumeSourceBuilder()
.withName("promtail-config")
.withItems(new KeyToPath("promtail.yaml", null, "promtail.yaml"))
.build();
Volume volume = new VolumeBuilder().withName("config").withNewConfigMapLike(configMapVolumeSource).endConfigMap().build();
Volume volume2 = new VolumeBuilder().withName("config2").withNewConfigMapLike(configMapVolumeSource).endConfigMap().build();
assertThat(podSpec.getVolumes()).containsExactly(volume, volume2);
}
@Test
public void deployWithVolumesAndVolumeMountsOnAdditionalContainerAbsentVolumeMount() throws Exception {
AppDefinition definition = new AppDefinition("app-test", null);
Map<String, String> props = new HashMap<>();
props.put("spring.cloud.deployer.kubernetes.volumes", "[{name: 'config', configMap: {name: promtail-config, items: [{key: promtail.yaml, path: promtail.yaml}]}},{name: 'config2', configMap: {name: promtail-config, items: [{key: promtail.yaml, path: promtail.yaml}]}}]");
// both containers reference config.
props.put("spring.cloud.deployer.kubernetes.additional-containers", "[{name: 'promtail',image: image-path-of-promtail, ports:[{protocol: TCP,containerPort: 8080}],args: [\"-config.file=/home/conf/promtail.yaml\"],volumeMounts: [{name: 'config', mountPath: '/home/conf'}]},{name: 'promtail2',image: image-path-of-promtail, ports:[{protocol: TCP,containerPort: 8080}],args: [\"-config.file=/home/conf/promtail.yaml\"],volumeMounts: [{name: 'config', mountPath: '/home/conf'}]}]");
AppDeploymentRequest appDeploymentRequest = new AppDeploymentRequest(definition, getResource(), props);

deployer = k8sAppDeployer();
PodSpec podSpec = deployer.createPodSpec(appDeploymentRequest);

ConfigMapVolumeSource configMapVolumeSource = new ConfigMapVolumeSourceBuilder()
.withName("promtail-config")
.withItems(new KeyToPath("promtail.yaml", null, "promtail.yaml"))
.build();
Set<String> volumeNames = podSpec.getVolumes().stream().map(v -> v.getName()).collect(Collectors.toSet());
assertThat(volumeNames).doesNotContain("config2");
Volume volume = new VolumeBuilder().withName("config").withNewConfigMapLike(configMapVolumeSource).endConfigMap().build();
assertThat(podSpec.getVolumes()).containsExactly(volume);

}
@Test
public void deployWithNodeSelectorGlobalProperty() throws Exception {
AppDefinition definition = new AppDefinition("app-test", null);
Expand Down

0 comments on commit 65dbb7d

Please sign in to comment.