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 14, 2018
1 parent 2ccfce1 commit 9335bba
Show file tree
Hide file tree
Showing 19 changed files with 328 additions and 87 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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,89 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 @@ -40,6 +40,7 @@
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;
Expand Down Expand Up @@ -103,12 +104,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 +153,21 @@ 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;
}
} 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
25 changes: 24 additions & 1 deletion core/src/main/java/io/fabric8/maven/core/util/ResourceUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@
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;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.maven.plugin.MojoExecutionException;
import org.json.JSONObject;

/**
Expand Down Expand Up @@ -71,7 +75,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 +83,26 @@ 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;
}

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
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import io.fabric8.maven.core.config.BuildRecreateMode;
import io.fabric8.maven.core.config.OpenShiftBuildStrategy;
import io.fabric8.maven.core.service.BuildService;
import io.fabric8.maven.core.service.DefaultBinaryInputArchiveBuilder;
import io.fabric8.maven.core.service.Fabric8ServiceException;
import io.fabric8.maven.core.util.WebServerEventCollector;
import io.fabric8.maven.docker.assembly.ArchiverCustomizer;
Expand Down Expand Up @@ -167,7 +168,7 @@ public void testSuccessfulBuild() throws Exception {
LOG.info("Current read timeout is : {}", client.getHttpClient().readTimeoutMillis());
LOG.info("Retry on failure : {}", client.getHttpClient().retryOnConnectionFailure());
OpenshiftBuildService service = new OpenshiftBuildService(client, logger, dockerServiceHub, config);
service.build(image);
service.build(image, new DefaultBinaryInputArchiveBuilder(config));

// we should Foadd a better way to assert that a certain call has been made
assertTrue(mockServer.getRequestCount() > 8);
Expand Down Expand Up @@ -201,7 +202,7 @@ public void testSuccessfulBuildSecret() throws Exception {
LOG.info("Current read timeout is : {}", client.getHttpClient().readTimeoutMillis());
LOG.info("Retry on failure : {}", client.getHttpClient().retryOnConnectionFailure());
OpenshiftBuildService service = new OpenshiftBuildService(client, logger, dockerServiceHub, config);
service.build(image);
service.build(image, new DefaultBinaryInputArchiveBuilder(config));

// we should Foadd a better way to assert that a certain call has been made
assertTrue(mockServer.getRequestCount() > 8);
Expand All @@ -227,7 +228,7 @@ public void testFailedBuild() throws Exception {

OpenShiftClient client = mockServer.createOpenShiftClient();
OpenshiftBuildService service = new OpenshiftBuildService(client, logger, dockerServiceHub, config);
service.build(image);
service.build(image, new DefaultBinaryInputArchiveBuilder(config));
}

@Test(expected = Fabric8ServiceException.class)
Expand All @@ -238,7 +239,7 @@ public void testFailedBuildSecret() throws Exception {

OpenShiftClient client = mockServer.createOpenShiftClient();
OpenshiftBuildService service = new OpenshiftBuildService(client, logger, dockerServiceHub, config);
service.build(image);
service.build(image, new DefaultBinaryInputArchiveBuilder(config));
}

@Test
Expand All @@ -254,7 +255,7 @@ public void testSuccessfulSecondBuild() throws Exception {

OpenShiftClient client = mockServer.createOpenShiftClient();
OpenshiftBuildService service = new OpenshiftBuildService(client, logger, dockerServiceHub, config);
service.build(image);
service.build(image, new DefaultBinaryInputArchiveBuilder(config));

assertTrue(mockServer.getRequestCount() > 8);
collector.assertEventsRecordedInOrder("build-config-check", "patch-build-config", "pushed");
Expand Down Expand Up @@ -291,7 +292,7 @@ public void checkTarPackage() throws Exception {
.build()
).build();

service.createBuildArchive(imageWithEnv);
service.build(imageWithEnv, new DefaultBinaryInputArchiveBuilder(config));

final List<ArchiverCustomizer> customizer = new LinkedList<>();
new Verifications() {{
Expand Down Expand Up @@ -348,7 +349,7 @@ public void checkTarPackageSecret() throws Exception {
.build()
).build();

service.createBuildArchive(imageWithEnv);
service.build(imageWithEnv, new DefaultBinaryInputArchiveBuilder(config));

final List<ArchiverCustomizer> customizer = new LinkedList<>();
new Verifications() {{
Expand Down
Loading

0 comments on commit 9335bba

Please sign in to comment.