Skip to content

Commit

Permalink
Updates for podman
Browse files Browse the repository at this point in the history
  • Loading branch information
BarDweller committed Apr 15, 2024
1 parent e652f53 commit 0a7fbbd
Show file tree
Hide file tree
Showing 46 changed files with 1,962 additions and 246 deletions.
15 changes: 10 additions & 5 deletions client/src/main/java/dev/snowdrop/buildpack/BuilderImage.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public BuilderImage(BuilderImage original, boolean addedExtensions, ImageReferen
this.runImages = original.runImages;
this.builderSupportedPlatforms = original.builderSupportedPlatforms;
this.hasExtensions = original.hasExtensions || addedExtensions;
System.out.println("Extended builder image hasExtensions? "+hasExtensions+" orig?"+original.hasExtensions+" add?"+addedExtensions);
this.image = extended;
}

Expand Down Expand Up @@ -72,15 +71,21 @@ public BuilderImage(DockerConfig dc, PlatformConfig pc, ImageReference runImage,
}

String xtnLayers = ii.labels.get("io.buildpacks.extension.layers");
System.out.println("Builder image got xtnLayers label "+xtnLayers);
//if xtnLayers is absent, or is just the empty json {}, there are no extensions.
if(xtnLayers!=null && !xtnLayers.isEmpty()){
xtnLayers = xtnLayers.trim();
xtnLayers.replaceAll("\\\\w", "");
if(xtnLayers.equals("{}")){
xtnLayers = null;
}
}
hasExtensions = (xtnLayers!=null && !xtnLayers.isEmpty());
System.out.println("BuilderImage hasExtensions? "+hasExtensions);

//defer the calculation of run images to the getter, because we
//need to know the selected platform level to know how to find the run metadata.
metadataJson = ii.labels.get("io.buildpacks.builder.metadata");
this.metadataJson = ii.labels.get("io.buildpacks.builder.metadata");
this.runImage = runImage;
runImages = null;
this.runImages = null;

builderSupportedPlatforms = BuildpackMetadata.getSupportedPlatformsFromMetadata(metadataJson);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import dev.snowdrop.buildpack.config.PlatformConfig;
import dev.snowdrop.buildpack.docker.BuildContainerUtils;
import dev.snowdrop.buildpack.lifecycle.LifecycleExecutor;
import dev.snowdrop.buildpack.lifecycle.Version;
import dev.snowdrop.buildpack.utils.LifecycleMetadata;

public class BuildpackBuild {
Expand Down Expand Up @@ -72,8 +73,8 @@ public int build(){
config.getPlatformConfig(),
builder);

System.out.println("Selected platform level "+activePlatformLevel);

//precache the runimages in the orig builder before extending it.
builder.getRunImages(new Version(activePlatformLevel));
//create the extended builder image.
BuilderImage extendedBuilder = BuildContainerUtils.createBuildImage(config.getDockerConfig().getDockerClient(),
builder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.github.dockerjava.api.DockerClient;

import dev.snowdrop.buildpack.BuildpackException;
import dev.snowdrop.buildpack.docker.DockerClientUtils;
import io.sundr.builder.annotations.Buildable;

Expand Down Expand Up @@ -34,6 +35,12 @@ public DockerConfig(
this.dockerNetwork = dockerNetwork;
this.useDaemon = useDaemon != null ? useDaemon : Boolean.TRUE; //default daemon to true for back compat.
this.dockerClient = dockerClient != null ? dockerClient : DockerClientUtils.getDockerClient(this.dockerHost);

try{
this.dockerClient.pingCmd().exec();
}catch(Exception e){
throw new BuildpackException("Unable to verify docker settings", e);
}
}

public Integer getPullTimeout(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public void run() {
tae.setSize(0);
tae.setUserId(uid);
tae.setGroupId(gid);
tae.setMode(TarArchiveEntry.DEFAULT_DIR_MODE);
tout.putArchiveEntry(tae);
tout.closeArchiveEntry();
}
Expand Down Expand Up @@ -121,29 +122,37 @@ public static BuilderImage createBuildImage(DockerClient dc, BuilderImage baseBu
List<String> command = Stream.of("").collect(Collectors.toList());
String builderContainerId = ContainerUtils.createContainer(dc, baseBuilder.getImage().getReference(), command);

if(lifecycle!=null)
processBuildModule(dc, builderContainerId, lifecycle.getReference(), "/cnb/lifecycle", "/cnb");

if(extensions!=null)
for(ImageReference extension: extensions)
processBuildModule(dc, builderContainerId, extension.getReference(), "/cnb/extensions", "/cnb");

if(buildpacks!=null)
for(ImageReference buildpack: buildpacks)
processBuildModule(dc, builderContainerId, buildpack.getReference(), "/cnb/buildpacks", "/cnb");

populateMountPointDirs(dc, builderContainerId, baseBuilder.getUserId(), baseBuilder.getGroupId(),
Stream.of(LifecyclePhaseFactory.KANIKO_VOL_PATH,
LifecyclePhaseFactory.WORKSPACE_VOL_PATH,
LifecyclePhaseFactory.LAYERS_VOL_PATH,
LifecyclePhaseFactory.CACHE_VOL_PATH,
LifecyclePhaseFactory.LAUNCH_CACHE_VOL_PATH,
LifecyclePhaseFactory.PLATFORM_VOL_PATH,
LifecyclePhaseFactory.PLATFORM_VOL_PATH+LifecyclePhaseFactory.ENV_PATH_PREFIX)
.collect(Collectors.toList()));

return new BuilderImage(baseBuilder,
(extensions!=null && !extensions.isEmpty()),
new ImageReference(ContainerUtils.commitContainer(dc, builderContainerId)));
try{
if(lifecycle!=null)
processBuildModule(dc, builderContainerId, lifecycle.getReference(), "/cnb/lifecycle", "/cnb");

if(extensions!=null)
for(ImageReference extension: extensions)
processBuildModule(dc, builderContainerId, extension.getReference(), "/cnb/extensions", "/cnb");

if(buildpacks!=null)
for(ImageReference buildpack: buildpacks)
processBuildModule(dc, builderContainerId, buildpack.getReference(), "/cnb/buildpacks", "/cnb");

populateMountPointDirs(dc, builderContainerId, baseBuilder.getUserId(), baseBuilder.getGroupId(),
Stream.of(LifecyclePhaseFactory.KANIKO_VOL_PATH,
LifecyclePhaseFactory.WORKSPACE_VOL_PATH,
LifecyclePhaseFactory.LAYERS_VOL_PATH,
LifecyclePhaseFactory.CACHE_VOL_PATH,
LifecyclePhaseFactory.LAUNCH_CACHE_VOL_PATH,
LifecyclePhaseFactory.DOCKER_SOCKET_PATH,
LifecyclePhaseFactory.PLATFORM_VOL_PATH,
LifecyclePhaseFactory.PLATFORM_VOL_PATH+LifecyclePhaseFactory.ENV_PATH_PREFIX)
.collect(Collectors.toList()));

//commit the live container with the modifications and return it as the new Builder Image.
return new BuilderImage(baseBuilder,
(extensions!=null && !extensions.isEmpty()),
new ImageReference(ContainerUtils.commitContainer(dc, builderContainerId)));
}finally{
if(builderContainerId!=null){
ContainerUtils.removeContainer(dc, builderContainerId);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public interface ContainerEntry {

public long getSize();

public Integer getMode();

public DataSupplier getDataSupplier();

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

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd;
import com.github.dockerjava.api.command.CopyArchiveToContainerCmd;
import com.github.dockerjava.api.command.CreateContainerCmd;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.exception.NotFoundException;
Expand Down Expand Up @@ -113,6 +114,7 @@ private static String createContainerInternal(DockerClient dc, String imageRefer
}

CreateContainerResponse ccr = ccc.exec();

return ccr.getId();
}

Expand All @@ -121,15 +123,15 @@ public static String commitContainer(DockerClient dc, String containerId) {
}

public static void removeContainer(DockerClient dc, String containerId) {
dc.removeContainerCmd(containerId).exec();
dc.removeContainerCmd(containerId).withForce(true).exec();
}

public static void addContentToContainer(DockerClient dc, String containerId, List<ContainerEntry> entries) {
addContentToContainer(dc, containerId, entries != null ? entries.toArray(new ContainerEntry[entries.size()]) : new ContainerEntry[0]);
}

public static void addContentToContainer(DockerClient dc, String containerId, ContainerEntry... entries) {
addContentToContainer(dc, containerId, "", 0, 0, entries);
addContentToContainer(dc, containerId, "", null, null, entries);
}

public static void addContentToContainer(DockerClient dc, String containerId, String pathInContainer, Integer userId,
Expand All @@ -138,8 +140,8 @@ public static void addContentToContainer(DockerClient dc, String containerId, St
}

public static void addContentToContainer(DockerClient dc, String containerId, String pathInContainer, Integer userId,
Integer groupId, String name, String content) {
addContentToContainer(dc, containerId, pathInContainer, userId, groupId, new StringContent(name, content).getContainerEntries());
Integer groupId, String name, Integer mode, String content) {
addContentToContainer(dc, containerId, pathInContainer, userId, groupId, new StringContent(name, mode, content).getContainerEntries());
}

/**
Expand All @@ -158,12 +160,13 @@ private static void addParents(TarArchiveOutputStream tout, Set<String> seenDirs
// add parents of this FIRST
addParents(tout, seenDirs, uid, gid, parent);

log.debug("adding "+parent+"/");
log.debug("adding "+parent+"/ to tar");
// and then add this =)
TarArchiveEntry tae = new TarArchiveEntry(parent + "/");
tae.setSize(0);
tae.setUserId(uid);
tae.setGroupId(gid);
tae.setGroupId(gid);
tae.setMode(TarArchiveEntry.DEFAULT_DIR_MODE);
tout.putArchiveEntry(tae);
tout.closeArchiveEntry();
}
Expand All @@ -182,14 +185,17 @@ public static void addContentToContainer(DockerClient dc, String containerId, St

public static void addContentToContainer(DockerClient dc, String containerId, String pathInContainer, Integer userId, Integer groupId, ContainerEntry... entries) {

log.info("Adding to container "+containerId+" pathInContainer "+pathInContainer);

Set<String> seenDirs = new HashSet<>();
// Don't add entry for "/", causes issues with tar format.
seenDirs.add("");

// use supplied pathInContainer, trim off trailing "/" where required.
final String path = (!pathInContainer.isEmpty() && pathInContainer.endsWith("/"))
final String containerPath = (!pathInContainer.isEmpty() && pathInContainer.endsWith("/"))
? pathInContainer.substring(0, pathInContainer.length() - 1)
: pathInContainer;

// set uid/gid to the supplied values, or 0 if not supplied.
final int uid = (userId != null) ? userId : 0;
final int gid = (groupId != null) ? groupId : 0;
Expand All @@ -212,18 +218,18 @@ public void run() {

if (entryPath.startsWith("/"))
entryPath = entryPath.substring(1);
String pathWithEntry = path + "/" + entryPath;

// important! adds the parent dirs for the entries with the correct uid/gid.
// (otherwise various buildpack tasks won't be able to write to them!)
addParents(tout, seenDirs, uid, gid, pathWithEntry);
addParents(tout, seenDirs, uid, gid, entryPath);

log.debug("adding "+pathWithEntry);
log.debug("adding "+entryPath+" to tar");
// add this file entry.
TarArchiveEntry tae = new TarArchiveEntry(pathWithEntry);
TarArchiveEntry tae = new TarArchiveEntry(entryPath);
tae.setSize(ve.getSize());
tae.setUserId(uid);
tae.setGroupId(gid);
tae.setGroupId(gid);
tae.setMode(0100000 + ve.getMode()); //0100000 means 'regular file'
tout.putArchiveEntry(tae);
DataSupplier cs = ve.getDataSupplier();
if(cs==null) {
Expand All @@ -245,10 +251,15 @@ public void run() {
}
};

log.info("Copying archive to container at "+containerPath);

Runnable reader = new Runnable() {
@Override
public void run() {
dc.copyArchiveToContainerCmd(containerId).withRemotePath("/").withTarInputStream(in).exec();
CopyArchiveToContainerCmd c = dc.copyArchiveToContainerCmd(containerId)
.withRemotePath(containerPath)
.withTarInputStream(in);
c.exec();
}
};

Expand Down Expand Up @@ -284,11 +295,8 @@ public static byte[] getFileFromContainer(DockerClient dc, String id, String pat
try{
TarArchiveEntry tarEntry = tarInput.getNextTarEntry();
while(tarEntry!=null){
//tarEntry.getName does not include path..
//if(path.equals(tarEntry.getName())){
copy(tarInput, file);
file.close();
//}
copy(tarInput, file);
file.close();
tarEntry = tarInput.getNextTarEntry();
}
return file.toByteArray();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package dev.snowdrop.buildpack.docker;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -12,7 +17,6 @@
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import com.github.dockerjava.transport.DockerHttpClient;


public class DockerClientUtils {
private static final Logger log = LoggerFactory.getLogger(DockerClientUtils.class);

Expand Down Expand Up @@ -46,15 +50,41 @@ public static DockerClient getDockerClient(String dockerHost) {

public static String getDockerHost() {
String dockerHost = System.getenv("DOCKER_HOST");
if (dockerHost != null && dockerHost.isEmpty()) {
if (dockerHost != null && dockerHost.isEmpty()) {
return dockerHost;
}

switch (OperatingSytem.getOperationSystem()) {
case WIN:
return "npipe:////./pipe/docker_engine";
default:
return "unix:///var/run/docker.sock";
case WIN:
return "npipe:////./pipe/docker_engine";
case LINUX: {
//test for presence of docker.
File dockerSock = new File("/var/run/docker.sock");
if(dockerSock.exists()){
return "unix:///var/run/docker.sock";
}

File podmanSock = new File("/var/run/podman.sock");
if(podmanSock.exists()){
return "unix:///var/run/podman.sock";
}

try{
int uid = (Integer)Files.getAttribute(Paths.get("/proc/self"), "unix:uid");
File podmanUserSock = new File("/var/run/user/"+uid+"/podman/podman.sock");
if(podmanUserSock.exists()){
return "unix:///var/run/user/1000/podman/podman.sock";
}
}catch(IOException io){
//ignore.
}

//none of the known linux filesystem locations had socket files, default to docker
//and assume the user has a plan we don't know about =)
return "unix:///var/run/docker.sock";
}
default:
return "unix:///var/run/docker.sock";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.stream.Collectors;

import dev.snowdrop.buildpack.BuildpackException;
import dev.snowdrop.buildpack.utils.FilePermissions;
import io.sundr.builder.annotations.Buildable;

@Buildable(generateBuilderPackage = true, builderPackage = "dev.snowdrop.buildpack.builder")
Expand All @@ -25,6 +26,8 @@ public class FileContent implements Content {
private final String prefix;
private final File file;
private final File root;
//delegate calls for permissions thru static, to enable testing.
private static FilePermissions filePermissions = new FilePermissions();

public FileContent(File file) {
this(DEFAULT_PREFIX, file);
Expand Down Expand Up @@ -83,6 +86,11 @@ public String getPath() {
UNIX_FILE_SEPARATOR);
}

@Override
public Integer getMode() {
return filePermissions.getPermissions(file);
}

@Override
public DataSupplier getDataSupplier() {
Path p = file.toPath();
Expand Down
Loading

0 comments on commit 0a7fbbd

Please sign in to comment.