Skip to content

Commit

Permalink
Change API to work better with Podman 5.0.0
Browse files Browse the repository at this point in the history
This makes port publications more explicit with regards to which
addresses should be bound. Additionally, it fixes some issues caused
by the move from slirp4netns to pasta as the podman default: The old
behaviour in podman when told to publish on address :: was to publish
on all IPv6 AND IPv4 addresses.  The new behaviour for pasta is to
only publish IPv6 (which is arguably what slirp4netns should have
been doing).

This also adds optional debug logging, and more configuration for
readiness checks.

Affects: containers/podman#22221
Fix: #3
  • Loading branch information
io7m committed Mar 31, 2024
1 parent 6f7de61 commit 4cc3d59
Show file tree
Hide file tree
Showing 11 changed files with 443 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,28 @@
/**
* The container configuration.
*
* @param projectName The project name
* @param podmanExecutable The podman executable
* @param startupWaitTime The startup wait time
* @param projectName The project name
* @param podmanExecutable The podman executable
* @param startupWaitTime The startup wait time
* @param livenessCheckPauseTime The pause time between liveness checks
* @param debugLogging Whether debug logging is enabled
*/

public record EContainerConfiguration(
RDottedName projectName,
String podmanExecutable,
Duration startupWaitTime,
Duration livenessCheckPauseTime)
Duration livenessCheckPauseTime,
boolean debugLogging)
{
/**
* The container configuration.
*
* @param projectName The project name
* @param podmanExecutable The podman executable
* @param startupWaitTime The startup wait time
* @param projectName The project name
* @param podmanExecutable The podman executable
* @param startupWaitTime The startup wait time
* @param livenessCheckPauseTime The pause time between liveness checks
* @param debugLogging Whether debug logging is enabled
*/

public EContainerConfiguration
Expand All @@ -67,7 +70,8 @@ public static EContainerConfiguration defaults(
projectName,
"podman",
Duration.ofSeconds(30L),
Duration.ofMillis(500L)
Duration.ofMillis(500L),
false
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright © 2024 Mark Raynsford <[email protected]> https://www.io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/


package com.io7m.ervilla.api;

import java.util.Objects;

/**
* The address to which to bind a port.
*/

public sealed interface EPortAddressType
{
/**
* @return The address string to be used externally to connect to the bound port
*/

String targetAddress();

/**
* Bind to all IPv4 addresses ("0.0.0.0").
*/

record AllIPv4()
implements EPortAddressType
{
@Override
public String targetAddress()
{
return "0.0.0.0";
}
}

/**
* Bind to all IPv6 addresses ("::").
*/

record AllIPv6()
implements EPortAddressType
{
@Override
public String targetAddress()
{
return "::";
}
}

/**
* Bind to all addresses ("0.0.0.0" and "::").
*/

record All()
implements EPortAddressType
{
@Override
public String targetAddress()
{
return "::";
}
}

/**
* Bind to a specific address.
*
* @param address The host address
*/

record Address(String address)
implements EPortAddressType
{
/**
* Bind to a specific address.
*/

public Address
{
Objects.requireNonNull(address, "address");
}

@Override
public String targetAddress()
{
return this.address;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,34 @@
package com.io7m.ervilla.api;

import java.util.Objects;
import java.util.Optional;

/**
* A request to publish a container port on the host.
*
* @param hostIP The host IP (or localhost, if not specified)
* @param hostAddress The host address to which to bind
* @param hostPort The host port
* @param containerPort The container port
* @param protocol The port protocol
*/

public record EPortPublish(
Optional<String> hostIP,
EPortAddressType hostAddress,
int hostPort,
int containerPort,
EPortProtocol protocol)
{
/**
* A request to publish a container port on the host.
*
* @param hostIP The host IP (or localhost, if not specified)
* @param hostAddress The host address to which to bind
* @param hostPort The host port
* @param containerPort The container port
* @param protocol The port protocol
*/

public EPortPublish
{
Objects.requireNonNull(hostIP, "hostIP");
Objects.requireNonNull(hostAddress, "hostAddress");
Objects.requireNonNull(protocol, "protocol");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.io7m.ervilla.api.EContainerSupervisorScope;
import com.io7m.ervilla.api.EContainerSupervisorType;
import com.io7m.ervilla.api.EContainerType;
import com.io7m.ervilla.api.EPortAddressType;
import com.io7m.ervilla.api.EPortPublish;
import com.io7m.ervilla.api.EVolumeMount;
import com.io7m.jdeferthrow.core.ExceptionTracker;
Expand Down Expand Up @@ -188,26 +189,49 @@ public void cleanUpOldContainersAndPods()
private static String portSpec(
final EPortPublish publish)
{
if (publish.hostIP().isPresent()) {
final var hostIP = publish.hostIP().get();
return "%s:%s:%s/%s".formatted(
hostIP,
Integer.valueOf(publish.hostPort()),
Integer.valueOf(publish.containerPort()),
switch (publish.protocol()) {
case TCP -> "tcp";
case UDP -> "udp";
}
);
}
return "%s:%s/%s".formatted(
Integer.valueOf(publish.hostPort()),
Integer.valueOf(publish.containerPort()),
switch (publish.protocol()) {
case TCP -> "tcp";
case UDP -> "udp";
return switch (publish.hostAddress()) {
case final EPortAddressType.Address address -> {
yield "%s:%s:%s/%s".formatted(
address.targetAddress(),
Integer.valueOf(publish.hostPort()),
Integer.valueOf(publish.containerPort()),
switch (publish.protocol()) {
case TCP -> "tcp";
case UDP -> "udp";
}
);
}
);
case final EPortAddressType.All all -> {
yield "%s:%s/%s".formatted(
Integer.valueOf(publish.hostPort()),
Integer.valueOf(publish.containerPort()),
switch (publish.protocol()) {
case TCP -> "tcp";
case UDP -> "udp";
}
);
}
case final EPortAddressType.AllIPv4 allIPv4 -> {
yield "0.0.0.0:%s:%s/%s".formatted(
Integer.valueOf(publish.hostPort()),
Integer.valueOf(publish.containerPort()),
switch (publish.protocol()) {
case TCP -> "tcp";
case UDP -> "udp";
}
);
}
case final EPortAddressType.AllIPv6 allIPv6 -> {
yield "[::]:%s:%s/%s".formatted(
Integer.valueOf(publish.hostPort()),
Integer.valueOf(publish.containerPort()),
switch (publish.protocol()) {
case TCP -> "tcp";
case UDP -> "udp";
}
);
}
};
}

private static String volumeSpec(
Expand Down Expand Up @@ -375,10 +399,16 @@ private EContainer createAndStartContainer(

private List<String> podman()
{
if (this.configuration.debugLogging()) {
return List.of(
this.configuration.podmanExecutable(),
"--log-level",
"debug"
);
}

return List.of(
this.configuration.podmanExecutable(),
"--log-level",
"debug"
this.configuration.podmanExecutable()
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package com.io7m.ervilla.postgres;

import com.io7m.ervilla.api.EPortAddressType;
import com.io7m.ervilla.api.EReadyCheckType;
import org.postgresql.PGProperty;
import org.slf4j.Logger;
Expand All @@ -35,14 +36,14 @@ public final class EPgReadyCheck implements EReadyCheckType
private static final Logger LOG =
LoggerFactory.getLogger(EPgReadyCheck.class);

private final String address;
private final EPortAddressType address;
private final int port;
private final String userName;
private final String password;
private final String database;

private EPgReadyCheck(
final String inAddress,
final EPortAddressType inAddress,
final int inPort,
final String inUserName,
final String inPassword,
Expand Down Expand Up @@ -73,7 +74,7 @@ private EPgReadyCheck(
*/

public static EReadyCheckType create(
final String inAddress,
final EPortAddressType inAddress,
final int inPort,
final String userName,
final String password,
Expand All @@ -89,7 +90,7 @@ public boolean isReady()
final var properties = new Properties();
properties.setProperty(PGProperty.USER.getName(), this.userName);
properties.setProperty(PGProperty.PASSWORD.getName(), this.password);
properties.setProperty(PGProperty.PG_HOST.getName(), this.address);
properties.setProperty(PGProperty.PG_HOST.getName(), this.address.targetAddress());
properties.setProperty(PGProperty.PG_PORT.getName(), Integer.toString(this.port));
properties.setProperty(PGProperty.PG_DBNAME.getName(), this.database);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
package com.io7m.ervilla.postgres;

import com.io7m.ervilla.api.EContainerSpec;
import com.io7m.ervilla.api.EPortAddressType;
import com.io7m.ervilla.api.EPortPublish;

import java.util.Optional;

import static com.io7m.ervilla.api.EPortProtocol.TCP;

/**
Expand Down Expand Up @@ -52,7 +51,7 @@ private EPgSpecs()
public static EContainerSpec.Builder builder(
final String repository,
final String version,
final Optional<String> address,
final EPortAddressType address,
final int hostPort,
final String databaseName,
final String databaseUser,
Expand All @@ -73,7 +72,7 @@ public static EContainerSpec.Builder builder(
.addEnvironmentVariable("POSTGRES_PASSWORD", databasePassword)
.addEnvironmentVariable("POSTGRES_USER", databaseUser)
.setReadyCheck(EPgReadyCheck.create(
address.orElse("localhost"),
address,
hostPort,
databaseUser,
databasePassword,
Expand All @@ -96,7 +95,7 @@ public static EContainerSpec.Builder builder(

public static EContainerSpec.Builder builderFromDockerIO(
final String version,
final Optional<String> address,
final EPortAddressType address,
final int hostPort,
final String databaseName,
final String databaseUser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,22 @@
*/

TimeUnit startupWaitTimeUnit() default TimeUnit.SECONDS;

/**
* @return The liveness check pause time
*/

long livenessCheckPauseTime() default 250L;

/**
* @return The liveness check pause time unit
*/

TimeUnit livenessCheckPauseTimeUnit() default TimeUnit.MILLISECONDS;

/**
* @return {@code true} if debug logging is enabled
*/

boolean debugLogging() default false;
}
Loading

0 comments on commit 4cc3d59

Please sign in to comment.