Skip to content

Commit

Permalink
Fix fabric8io#825 : More flexible S2I binary build data format
Browse files Browse the repository at this point in the history
  • Loading branch information
rohanKanojia committed Aug 24, 2018
1 parent 2ccfce1 commit 8beda35
Show file tree
Hide file tree
Showing 26 changed files with 484 additions and 111 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2016 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version
* 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package io.fabric8.maven.core.service;

import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.service.ServiceHub;

import java.io.File;

public interface BinaryInputArchiveBuilder {
void createBinaryInput(ServiceHub hub, File targetDirectory, ImageConfiguration imageConfiguration) throws Fabric8ServiceException;
File getBinaryInputTar();
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public interface BuildService {
*
* @param imageConfig the image to build
*/
void build(ImageConfiguration imageConfig) throws Fabric8ServiceException;
void build(ImageConfiguration imageConfig, BinaryInputArchiveBuilder binaryInputArchiveBuilder) throws Fabric8ServiceException;

/**
* Post processing step called after all images has been build
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright 2016 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version
* 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package io.fabric8.maven.core.service;

import io.fabric8.maven.core.util.IoUtil;
import io.fabric8.maven.docker.assembly.ArchiverCustomizer;
import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.service.ServiceHub;
import org.apache.maven.plugin.MojoExecutionException;
import org.codehaus.plexus.archiver.tar.TarArchiver;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

public class DefaultBinaryInputArchiveBuilder implements BinaryInputArchiveBuilder {

private BuildService.BuildServiceConfig config;
private File binaryInputTar = null;

public DefaultBinaryInputArchiveBuilder(BuildService.BuildServiceConfig config) {
this.config = config;
}

@Override
public void createBinaryInput(ServiceHub hub, File targetDir, ImageConfiguration imageConfiguration) throws Fabric8ServiceException {
// Adding S2I artifacts such as environment variables in S2I mode
ArchiverCustomizer customizer = getS2ICustomizer(imageConfiguration);

try {
// Create tar file with Docker archive
if (customizer != null) {
this.binaryInputTar = hub.getArchiveService().createDockerBuildArchive(imageConfiguration, config.getDockerMojoParameters(), customizer);
} else {
this.binaryInputTar = hub.getArchiveService().createDockerBuildArchive(imageConfiguration, config.getDockerMojoParameters());
}
} catch (MojoExecutionException e) {
throw new Fabric8ServiceException("Unable to create the build archive", e);
}
}

private ArchiverCustomizer getS2ICustomizer(ImageConfiguration imageConfiguration) throws Fabric8ServiceException {
try {
if (imageConfiguration.getBuildConfiguration() != null && imageConfiguration.getBuildConfiguration().getEnv() != null) {
String fileName = IoUtil.sanitizeFileName("s2i-env-" + imageConfiguration.getName());
final File environmentFile = new File(config.getBuildDirectory(), fileName);

try (PrintWriter out = new PrintWriter(new FileWriter(environmentFile))) {
for (Map.Entry<String, String> e : imageConfiguration.getBuildConfiguration().getEnv().entrySet()) {
out.println(e.getKey() + "=" + e.getValue());
}
}

return new ArchiverCustomizer() {
@Override
public TarArchiver customize(TarArchiver tarArchiver) throws IOException {
tarArchiver.addFile(environmentFile, ".s2i/environment");
return tarArchiver;
}
};
} else {
return null;
}
} catch (IOException e) {
throw new Fabric8ServiceException("Unable to add environment variables to the S2I build archive", e);
}
}

public File getBinaryInputTar() {
return binaryInputTar;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ public BuildService getBuildService() {
return (BuildService) this.services.get(BuildService.class).get();
}

public ServiceHub getDockerServiceHub() {
return dockerServiceHub;
}

public ArtifactResolverService getArtifactResolverService() {
return (ArtifactResolverService) this.services.get(ArtifactResolverService.class).get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.Objects;

import io.fabric8.maven.core.service.BinaryInputArchiveBuilder;
import io.fabric8.maven.core.service.BuildService;
import io.fabric8.maven.core.service.Fabric8ServiceException;
import io.fabric8.maven.docker.config.ImageConfiguration;
Expand All @@ -41,7 +42,7 @@ public DockerBuildService(ServiceHub dockerServiceHub, BuildServiceConfig config
}

@Override
public void build(ImageConfiguration imageConfig) throws Fabric8ServiceException {
public void build(ImageConfiguration imageConfig, BinaryInputArchiveBuilder binaryInputArchiveBuilder) throws Fabric8ServiceException {

io.fabric8.maven.docker.service.BuildService dockerBuildService = dockerServiceHub.getBuildService();
io.fabric8.maven.docker.service.BuildService.BuildContext dockerBuildContext = config.getDockerBuildContext();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
package io.fabric8.maven.core.service.openshift;

import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
Expand All @@ -40,16 +39,16 @@
import io.fabric8.kubernetes.client.Watcher;
import io.fabric8.kubernetes.client.dsl.LogWatch;
import io.fabric8.maven.core.config.OpenShiftBuildStrategy;
import io.fabric8.maven.core.service.BinaryInputArchiveBuilder;
import io.fabric8.maven.core.service.BuildService;
import io.fabric8.maven.core.service.Fabric8ServiceException;
import io.fabric8.maven.core.util.IoUtil;
import io.fabric8.maven.core.util.FileUtil;
import io.fabric8.maven.core.util.ResourceFileType;
import io.fabric8.maven.core.util.kubernetes.KubernetesClientUtil;
import io.fabric8.maven.core.util.kubernetes.KubernetesHelper;
import io.fabric8.maven.core.util.kubernetes.KubernetesResourceUtil;
import io.fabric8.maven.core.util.kubernetes.OpenshiftHelper;
import io.fabric8.maven.docker.access.AuthConfig;
import io.fabric8.maven.docker.assembly.ArchiverCustomizer;
import io.fabric8.maven.docker.assembly.DockerAssemblyManager;
import io.fabric8.maven.docker.config.AssemblyConfiguration;
import io.fabric8.maven.docker.config.BuildImageConfiguration;
Expand Down Expand Up @@ -103,12 +102,19 @@ public OpenshiftBuildService(OpenShiftClient client, Logger log, ServiceHub dock
}

@Override
public void build(ImageConfiguration imageConfig) throws Fabric8ServiceException {
public void build(ImageConfiguration imageConfig, BinaryInputArchiveBuilder binaryInputArchiveBuilder) throws Fabric8ServiceException {
String buildName = null;
try {
ImageName imageName = new ImageName(imageConfig.getName());
// Create an empty directory
File targetDir = createEmptyTargetDir();

// Fill the directory with the data in the right directory structure
binaryInputArchiveBuilder.createBinaryInput(dockerServiceHub, targetDir, imageConfig);

File dockerTar = createBuildArchive(imageConfig);
// Create the tar archive by tarring the directory
File dockerTar = binaryInputArchiveBuilder.getBinaryInputTar() != null ? binaryInputArchiveBuilder.getBinaryInputTar() : createTar(targetDir);

ImageName imageName = new ImageName(imageConfig.getName());

KubernetesListBuilder builder = new KubernetesListBuilder();

Expand Down Expand Up @@ -145,49 +151,29 @@ public void build(ImageConfiguration imageConfig) throws Fabric8ServiceException
}
}

protected File createBuildArchive(ImageConfiguration imageConfig) throws Fabric8ServiceException {
// Adding S2I artifacts such as environment variables in S2I mode
ArchiverCustomizer customizer = getS2ICustomizer(imageConfig);

try {
// Create tar file with Docker archive
File dockerTar;
if (customizer != null) {
dockerTar = dockerServiceHub.getArchiveService().createDockerBuildArchive(imageConfig, config.getDockerMojoParameters(), customizer);
} else {
dockerTar = dockerServiceHub.getArchiveService().createDockerBuildArchive(imageConfig, config.getDockerMojoParameters());
}
return dockerTar;
} catch (MojoExecutionException e) {
throw new Fabric8ServiceException("Unable to create the build archive", e);
}
private File createEmptyTargetDir() {
File targetDir = new File(config.getBuildDirectory(), "docker");
targetDir.mkdirs();
return targetDir;
}

private ArchiverCustomizer getS2ICustomizer(ImageConfiguration imageConfiguration) throws Fabric8ServiceException {
try {
if (imageConfiguration.getBuildConfiguration() != null && imageConfiguration.getBuildConfiguration().getEnv() != null) {
String fileName = IoUtil.sanitizeFileName("s2i-env-" + imageConfiguration.getName());
final File environmentFile = new File(config.getBuildDirectory(), fileName);
private File createTar(File targetDir) throws IOException {
TarArchiver tarArchiver = new TarArchiver();
tarArchiver.addDirectory(targetDir);

try (PrintWriter out = new PrintWriter(new FileWriter(environmentFile))) {
for (Map.Entry<String, String> e : imageConfiguration.getBuildConfiguration().getEnv().entrySet()) {
out.println(e.getKey() + "=" + e.getValue());
}
}

return new ArchiverCustomizer() {
@Override
public TarArchiver customize(TarArchiver tarArchiver) throws IOException {
tarArchiver.addFile(environmentFile, ".s2i/environment");
return tarArchiver;
}
};
} else {
return null;
// Delete previously existing tar files, if any
FileUtil.deleteFilesInDirectory(targetDir, new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
return s.endsWith(".tar");
}
} catch (IOException e) {
throw new Fabric8ServiceException("Unable to add environment variables to the S2I build archive", e);
}
});

File tarFile = File.createTempFile(config.getArtifactId().toString(), ".tar");
File destFile = new File(targetDir, config.getArtifactId() + ".tar");
tarArchiver.setDestFile(destFile);
tarArchiver.createArchive();
return tarFile;
}

private File getImageStreamFile(BuildServiceConfig config) {
Expand Down
18 changes: 18 additions & 0 deletions core/src/main/java/io/fabric8/maven/core/util/FileUtil.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.fabric8.maven.core.util;

import java.io.File;
import java.io.FilenameFilter;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
Expand Down Expand Up @@ -55,4 +56,21 @@ public static String getAbsolutePath(URL url) {
throw new RuntimeException(e);
}
}

public static boolean deleteFilesInDirectory(File parentDir, FilenameFilter filterNameFilter) {
boolean bAllFilesDeleted = true;
String[] files = parentDir.list(filterNameFilter);

if(files.length == 0) {
return false;
}

File fileToDelete = null;
for(String file : files) {
String absoluteFilePath = parentDir.getAbsolutePath() + File.separator + file;
fileToDelete = new File(absoluteFilePath);
bAllFilesDeleted &= fileToDelete.delete();
}
return bAllFilesDeleted;
}
}
35 changes: 33 additions & 2 deletions core/src/main/java/io/fabric8/maven/core/util/ResourceUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
package io.fabric8.maven.core.util;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
Expand Down Expand Up @@ -71,7 +74,6 @@ public static File save(File file, Object data, ResourceFileType type) throws IO
return output;
}


public static String toYaml(Object resource) throws JsonProcessingException {
return serializeAsString(resource, ResourceFileType.yaml);
}
Expand All @@ -80,6 +82,35 @@ public static String toJson(Object resource) throws JsonProcessingException {
return serializeAsString(resource, ResourceFileType.json);
}

public static File getArchiveFile(File directory, String[] jarOrWars) throws IOException{
long maxSize = 0;
File projectArchiveId = null;
for (String jarOrWar : jarOrWars) {
File archiveFile = new File(directory, jarOrWar);
JarFile archive = new JarFile(archiveFile);
Manifest mf = archive.getManifest();
Attributes mainAttributes = mf.getMainAttributes();
if (mainAttributes != null) {
long size = archiveFile.length();
// Take the largest jar / war file found
if (size > maxSize) {
maxSize = size;
projectArchiveId = archiveFile;
}
}
}
return projectArchiveId;
}

public static String[] getFileListOfExtension(File directory, final String extension) {
return directory.list(new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
return s.endsWith(extension);
}
});
}

private static String serializeAsString(Object resource, ResourceFileType resourceFileType) throws JsonProcessingException {
return getObjectMapper(resourceFileType).writeValueAsString(resource);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.fabric8.maven.core.service.kubernetes;

import io.fabric8.maven.core.service.DefaultBinaryInputArchiveBuilder;
import io.fabric8.maven.docker.config.BuildImageConfiguration;
import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.service.BuildService;
Expand Down Expand Up @@ -59,7 +60,7 @@ public void testSuccessfulBuild() throws Exception {
).build();

DockerBuildService service = new DockerBuildService(hub, config);
service.build(image);
service.build(image, new DefaultBinaryInputArchiveBuilder(config));

new FullVerificationsInOrder() {{
buildService.buildImage(image, context);
Expand Down
Loading

0 comments on commit 8beda35

Please sign in to comment.