I am working on integration testing for an SMB share using Testcontainers and am facing challenges with container startup. Could you assist me in finding a simple basic configuration and approach for testing SMB shares with Testcontainers?
Current implementation of the test setup:
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.utility.DockerImageName;
import java.io.IOException;
import static org.assertj.core.api.Assertions.assertThat;
public class SmbContainerTest {
private static GenericContainer<?> smbContainer;
@BeforeAll
public static void setUp() throws IOException, InterruptedException {
smbContainer = new GenericContainer<>(DockerImageName.parse("dperson/samba"))
.withExposedPorts(445)
.withLogConsumer(new Slf4jLogConsumer(logger))
.withCommand("-p", "-u", "smbuser;smbpassword", "-s", "share;/srv/samba/share;yes;no;yes");
smbContainer.start();
// Create the share directory and set permissions
execInContainer("mkdir -p /srv/samba/share");
execInContainer("chmod 777 /srv/samba/share");
// Update smb.conf to include the share configuration
String smbConfUpdate = "echo "[share]\n" +
"path = /srv/samba/share\n" +
"browsable = yes\n" +
"writable = yes\n" +
"guest ok = yes\n" +
"read only = no" >> /etc/samba/smb.conf";
execInContainer(smbConfUpdate);
// Restart the smbd service
execInContainer("pkill smbd");
execInContainer("smbd");
}
@AfterAll
public static void tearDown() {
if (smbContainer != null) {
smbContainer.stop();
}
}
@Test
public void testSmbShare() throws IOException, InterruptedException {
// Verify the new share
String result = execInContainer("smbclient -L \\localhost -U smbuser%smbpassword -m SMB3");
assertThat(result).contains("Sharename Type Comment");
assertThat(result).contains("IPC$ IPC IPC Service (Samba Server)");
}
private static String execInContainer(String command) throws IOException, InterruptedException {
String[] commands = {"sh", "-c", command};
org.testcontainers.containers.Container.ExecResult execResult = smbContainer.execInContainer(commands);
String stdout = execResult.getStdout();
String stderr = execResult.getStderr();
int exitCode = execResult.getExitCode();
logger.info("Command: {} | Exit Code: {} | Stdout: {} | Stderr: {}", command, exitCode, stdout, stderr);
assertThat(exitCode).isEqualTo(0);
return stdout;
}
}
However, I am encountering the following exception during container startup:
Retry limit hit with exception
org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
at app//org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:88)
at app//org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:344)
at app//org.testcontainers.containers.GenericContainer.start(GenericContainer.java:330)
at app//SambaShareTest.setupSpec(SmbIntegrationSpec.groovy:17)
Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
at app//org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:563)
at app//org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:354)
at app//org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
... 3 more
Caused by: org.testcontainers.shaded.org.awaitility.core.ConditionTimeoutException: org.testcontainers.containers.GenericContainer$$Lambda/0x0000007001385e88 expected the predicate to return <true> but it returned <false> for input of <InspectContainerResponse(args=[--, /usr/bin/samba.sh, -u, smbuser;smbpassword, -s, shared;/mount, -p], config=ContainerConfig(attachStderr=false, attachStdin=false, attachStdout=false, cmd=[-u, smbuser;smbpassword, -s, shared;/mount, -p], domainName=, entrypoint=[/sbin/tini, --, /usr/bin/samba.sh], env=[PASSWORD=smbpassword, USER=smbuser, SHARE=shared:/mount, PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin], exposedPorts=[137/udp, 138/udp, 139/tcp, 445/tcp], hostName=13851a981764, image=dperson/samba:latest, labels={org.testcontainers=true, org.testcontainers.lang=java, org.testcontainers.sessionId=3dd41a28-375c-47b2-8193-e4a6a7fd595a, org.testcontainers.version=1.19.8}, macAddress=null, networkDisabled=null, onBuild=null, stdinOpen=false, portSpecs=null, stdInOnce=false, tty=false, user=, volumes={/etc={}, /run/samba={}, /var/cache/samba={}, /var/lib/samba={}, /var/log/samba={}}, workingDir=, healthCheck=HealthCheck(interval=60000000000, timeout=15000000000, test=[CMD-SHELL, smbclient -L \localhost -U % -m SMB3], retries=null, startPeriod=null, startInterval=null)), created=2024-08-09T09:52:52.368722503Z, driver=overlay2, execDriver=null, hostConfig=HostConfig(binds=[], blkioWeight=0, blkioWeightDevice=null, blkioDeviceReadBps=null, blkioDeviceWriteBps=null, blkioDeviceReadIOps=null, blkioDeviceWriteIOps=null, memorySwappiness=null, nanoCPUs=0, capAdd=null, capDrop=null, containerIDFile=, cpuPeriod=0, cpuRealtimePeriod=0, cpuRealtimeRuntime=0, cpuShares=0, cpuQuota=0, cpusetCpus=, cpusetMems=, devices=null, deviceCgroupRules=null, deviceRequests=null, diskQuota=null, dns=null, dnsOptions=null, dnsSearch=null, extraHosts=[], groupAdd=null, ipcMode=shareable, cgroup=, links=[], logConfig=LogConfig(type=json-file, config={}), lxcConf=null, memory=0, memorySwap=0, memoryReservation=0, kernelMemory=null, networkMode=bridge, oomKillDisable=null, init=null, autoRemove=false, oomScoreAdj=0, portBindings={445/tcp=[Lcom.github.dockerjava.api.model.Ports$Binding;@36f7d7b}, privileged=false, publishAllPorts=false, readonlyRootfs=false, restartPolicy=no, ulimits=null, cpuCount=0, cpuPercent=0, ioMaximumIOps=0, ioMaximumBandwidth=0, volumesFrom=[], mounts=null, pidMode=, isolation=null, securityOpts=null, storageOpt=null, cgroupParent=, volumeDriver=, shmSize=67108864, pidsLimit=null, runtime=runc, tmpFs=null, utSMode=, usernsMode=, sysctls=null, consoleSize=[0, 0], cgroupnsMode=private), hostnamePath=/var/lib/docker/containers/13851a981764124550fa913839e34765b447a20beebb6dc1c136db833835bf93/hostname, hostsPath=/var/lib/docker/containers/13851a981764124550fa913839e34765b447a20beebb6dc1c136db833835bf93/hosts, logPath=/var/lib/docker/containers/13851a981764124550fa913839e34765b447a20beebb6dc1c136db833835bf93/13851a981764124550fa913839e34765b447a20beebb6dc1c136db833835bf93-json.log, id=13851a981764124550fa913839e34765b447a20beebb6dc1c136db833835bf93, sizeRootFs=null, sizeRw=null, imageId=sha256:216f21e9a995109fb6befd2eb7ec811d7ad7b98a030e74dfa4bb1c8dbc2bc103, mountLabel=, name=/charming_poincare, restartCount=0, networkSettings=NetworkSettings(bridge=, sandboxId=, hairpinMode=false, linkLocalIPv6Address=, linkLocalIPv6PrefixLen=0, ports={}, sandboxKey=, secondaryIPAddresses=null, secondaryIPv6Addresses=null, endpointID=, gateway=, portMapping=null, globalIPv6Address=, globalIPv6PrefixLen=0, ipAddress=, ipPrefixLen=0, ipV6Gateway=, macAddress=, networks={bridge=ContainerNetwork(ipamConfig=null, links=[], aliases=null, networkID=1f712048222b76c9dcaeda9be2f1a84854a528dbce5a9ba282d8273f302d148f, endpointId=, gateway=, ipAddress=, ipPrefixLen=0, ipV6Gateway=, globalIPv6Address=, globalIPv6PrefixLen=0, macAddress=)}), path=/sbin/tini, processLabel=, resolvConfPath=/var/lib/docker/containers/13851a981764124550fa913839e34765b447a20beebb6dc1c136db833835bf93/resolv.conf, execIds=null, state=InspectContainerResponse.ContainerState(status=exited, running=false, paused=false, restarting=false, oomKilled=false, dead=false, pid=0, exitCode=1, error=, startedAt=2024-08-09T09:52:52.425761878Z, finishedAt=2024-08-09T09:52:52.528393087Z, health=HealthState(status=unhealthy, failingStreak=0, log=[])), volumes=null, volumesRW=null, node=null, mounts=[InspectContainerResponse.Mount(name=18d91d9f1e569fa22b03d20fd4dd7f47987368f238436c3e7418dfeea35aa551, source=/var/lib/docker/volumes/18d91d9f1e569fa22b03d20fd4dd7f47987368f238436c3e7418dfeea35aa551/_data, destination=/etc, driver=local, mode=, rw=true), InspectContainerResponse.Mount(name=d6fa42fb4974ff4439f3657b66cea772d4240ff6fdd40b9b134b0dd3e79a591b, source=/var/lib/docker/volumes/d6fa42fb4974ff4439f3657b66cea772d4240ff6fdd40b9b134b0dd3e79a591b/_data, destination=/run/samba, driver=local, mode=, rw=true), InspectContainerResponse.Mount(name=a31475d26e46dbb6e250037532c1bfdb13f9352b82ed6a4a2fb96786e17e31ae, source=/var/lib/docker/volumes/a31475d26e46dbb6e250037532c1bfdb13f9352b82ed6a4a2fb96786e17e31ae/_data, destination=/var/cache/samba, driver=local, mode=, rw=true), InspectContainerResponse.Mount(name=ed362d4fc056534c7069545678a1619e972905b9b27cccfdda5e5267da65cafc, source=/var/lib/docker/volumes/ed362d4fc056534c7069545678a1619e972905b9b27cccfdda5e5267da65cafc/_data, destination=/var/lib/samba, driver=local, mode=, rw=true), InspectContainerResponse.Mount(name=a899bcc06c9b856911ba1eb1cde93773fe00775bb2f80cc82e77360bbf3934e8, source=/var/lib/docker/volumes/a899bcc06c9b856911ba1eb1cde93773fe00775bb2f80cc82e77360bbf3934e8/_data, destination=/var/log/samba, driver=local, mode=, rw=true)], graphDriver=GraphDriver(name=overlay2, data=GraphData(rootDir=null, deviceId=null, deviceName=null, deviceSize=null, dir=null)), platform=linux)> within 5 seconds.
at app//org.testcontainers.shaded.org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
at app//org.testcontainers.shaded.org.awaitility.core.AbstractHamcrestCondition.await(AbstractHamcrestCondition.java:86)
at app//org.testcontainers.shaded.org.awaitility.core.ConditionFactory.until(ConditionFactory.java:985)
at app//org.testcontainers.shaded.org.awaitility.core.ConditionFactory.until(ConditionFactory.java:691)
at app//org.testcontainers.shaded.org.awaitility.core.ConditionFactory.until(ConditionFactory.java:708)
at app//org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:466)
... 5 more
**```
Please provide guidance on how to properly configure and test SMB shares using Testcontainers?** Any insights or recommendations would be greatly appreciated.