Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

189 sk #5

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
117 changes: 64 additions & 53 deletions boost-common/pom.xml
Original file line number Diff line number Diff line change
@@ -1,64 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2018 IBM Corporation and others. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v1.0 which accompanies this distribution,
and is available at http://www.eclipse.org/legal/epl-v10.html Contributors:
IBM Corporation - initial API and implementation -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v1.0 which accompanies this distribution,
and is available at http://www.eclipse.org/legal/epl-v10.html Contributors:
IBM Corporation - initial API and implementation -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>io.openliberty.boost</groupId>
<artifactId>boost-common</artifactId>
<version>0.1.2-SNAPSHOT</version>
<groupId>io.openliberty.boost</groupId>
<artifactId>boost-common</artifactId>
<version>0.1.2-SNAPSHOT</version>

<url>https://github.com/OpenLiberty/boost-common</url>
<url>https://github.com/OpenLiberty/boost-common</url>

<parent>
<groupId>net.wasdev.maven.parent</groupId>
<artifactId>parent</artifactId>
<version>1.4</version>
<relativePath />
</parent>
<parent>
<groupId>net.wasdev.maven.parent</groupId>
<artifactId>parent</artifactId>
<version>1.4</version>
<relativePath />
</parent>

<licenses>
<license>
<name>Eclipse Public License 1.0 (EPL-1.0)</name>
<url>https://raw.github.com/OpenLiberty/boost/master/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>
<licenses>
<license>
<name>Eclipse Public License 1.0 (EPL-1.0)</name>
<url>https://raw.github.com/OpenLiberty/boost/master/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>

<scm>
<connection>scm:git:[email protected]:OpenLiberty/boost-common.git</connection>
<developerConnection>scm:git:[email protected]:OpenLiberty/boost-common.git</developerConnection>
<url>[email protected]:OpenLiberty/boost-common.git</url>
<tag>HEAD</tag>
</scm>
<scm>
<connection>scm:git:[email protected]:OpenLiberty/boost-common.git</connection>
<developerConnection>scm:git:[email protected]:OpenLiberty/boost-common.git</developerConnection>
<url>[email protected]:OpenLiberty/boost-common.git</url>
<tag>HEAD</tag>
</scm>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>net.wasdev.wlp.common</groupId>
<artifactId>ci.common</artifactId>
<version>1.3.3</version>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.spotify</groupId>
<artifactId>docker-client</artifactId>
<version>8.11.7</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>net.wasdev.wlp.common</groupId>
<artifactId>ci.common</artifactId>
<version>1.3.3</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package io.openliberty.boost.common.docker;

import java.util.regex.Pattern;

import com.spotify.docker.client.DefaultDockerClient;
import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.auth.RegistryAuthSupplier;
import com.spotify.docker.client.exceptions.DockerCertificateException;

import io.openliberty.boost.common.BoostException;
import io.openliberty.boost.common.BoostLoggerI;

public interface AbstractDockerI {

public void execute(DockerClient dockerClient) throws BoostException;

public RegistryAuthSupplier createRegistryAuthSupplier() throws BoostException;

// Default methods

default public String getImageName(String repository, String tag) {
return repository + ":" + tag;
}

default public boolean isTagValid(String tag) {
return Pattern.matches("[\\w][\\w.-]{0,127}", tag);
}

default public boolean isRepositoryValid(String repository) {
String nameRegExp = "[a-z0-9]+((?:[._]|__|[-]*)[a-z0-9]+)*?";
String domain = "(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])";
String domainRegExp = domain + "(\\." + domain + ")*?" + "(:[0-9]+)?";

String repositoryRegExp = "(" + domainRegExp + "\\/)?" + nameRegExp + "(\\/" + nameRegExp + ")*?";

return Pattern.matches(repositoryRegExp, repository);
}

default public DockerClient getDockerClient(boolean useProxy) throws BoostException {
final RegistryAuthSupplier authSupplier = createRegistryAuthSupplier();
try {
return DefaultDockerClient.fromEnv().registryAuthSupplier(authSupplier).useProxy(useProxy).build();
} catch (DockerCertificateException e) {
throw new BoostException("Problem loading Docker certificates", e);
}
}

default public boolean isValidDockerConfig(BoostLoggerI log, String repository, String tag, String artifactId) throws BoostException {
if (repository.equals(artifactId) && !repository.equals(repository.toLowerCase())) {
repository = artifactId.toLowerCase();
log.debug(
"Applying all lower case letters to the default repository name to build the Docker image successfully");
}

if (!isRepositoryValid(repository)) {
if (repository.equals(artifactId)) {
throw new BoostException(
"The default repository name ${project.artifactId} cannot be used to build the image because it is not a valid repository name.");
} else {
throw new BoostException("The <repository> parameter is not configured with a valid name");
}
}
if (!isTagValid(tag)) {
throw new BoostException("The <tag> parameter is not configured with a valid name");
}
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*******************************************************************************
* Copyright (c) 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package io.openliberty.boost.common.docker;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Map;

import com.google.gson.Gson;
import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.DockerClient.BuildParam;
import com.spotify.docker.client.exceptions.DockerException;

import io.openliberty.boost.common.BoostException;
import io.openliberty.boost.common.BoostLoggerI;
import io.openliberty.boost.common.docker.dockerizer.spring.DockerizeLibertySpringBootJar;
import io.openliberty.boost.common.docker.dockerizer.spring.DockerizeSpringBootClasspath;
import io.openliberty.boost.common.docker.dockerizer.spring.DockerizeSpringBootJar;
import io.openliberty.boost.common.docker.dockerizer.spring.SpringDockerizer;

public abstract interface DockerBuildI extends AbstractDockerI {

public File getAppArchive() throws BoostException;

// Default methods

default public void dockerBuild(String dockerizer, DockerClient dockerClient, File projectDirectory,
File outputDirectory, String springBootVersion, boolean pullNewerImage, boolean noCache,
Map<String, String> buildArgs, String repository, String tag, BoostLoggerI log) throws BoostException {
try {
File appArchive = getAppArchive();

// Create a Dockerfile for the application
SpringDockerizer springDockerizer = getDockerizer(dockerizer, projectDirectory, outputDirectory, appArchive,
springBootVersion, log);
springDockerizer.createDockerFile();
springDockerizer.createDockerIgnore();

buildDockerImage(projectDirectory.toPath(), dockerClient, springDockerizer, pullNewerImage, noCache,
buildArgs, repository, tag, log);
} catch (Exception e) {
throw new BoostException(e.getMessage(), e);
}
}

default public SpringDockerizer getDockerizer(String dockerizer, File projectDirectory, File outputDirectory,
File appArchive, String springBootVersion, BoostLoggerI log) {

// TODO: Needed future enhancements:
// 1. Is it Spring or something else? sense with
// MavenProjectUtil.findSpringBootVersion(project);
// 2. Use OpenJ9 or HotSpot? sense with property boost.docker.jvm
if ("jar".equalsIgnoreCase(dockerizer)) {
return new DockerizeSpringBootJar(projectDirectory, outputDirectory, appArchive, springBootVersion, log);
}
if ("classpath".equalsIgnoreCase(dockerizer)) {
return new DockerizeSpringBootClasspath(projectDirectory, outputDirectory, appArchive, springBootVersion,
log);
}
// TODO: Maybe don't make the Spring Boot dockerizer default after EE stuff is
// added
// The current property values of 'jar', 'classpath' and 'liberty' are
// intentionally
// generic so that they can be applied irrespective of the project type (Spring
// vs EE)
return new DockerizeLibertySpringBootJar(projectDirectory, outputDirectory, appArchive, springBootVersion, log);
}

/**
* Use the DockerClient to build the image
*
*/
default public void buildDockerImage(Path baseDir, DockerClient dockerClient, SpringDockerizer dockerizer,
boolean pullNewerImage, boolean noCache, Map<String, String> buildArgs, String repository, String tag,
BoostLoggerI log) throws BoostException, IOException {
final DockerLoggingProgressHandler progressHandler = new DockerLoggingProgressHandler(log);
final String imageName = getImageName(repository, tag);
BuildParam[] buidParams = getBuildParams(dockerizer, pullNewerImage, noCache, buildArgs);
log.info(""); // Adding empty log for formatting purpose
log.info("Building image: " + imageName);
try {
dockerClient.build(baseDir, imageName, progressHandler, buidParams);
} catch (DockerException | InterruptedException e) {
throw new BoostException("Unable to build image", e);
}
}

default BuildParam[] getBuildParams(SpringDockerizer dockerizer, boolean pullNewerImage, boolean noCache,
Map<String, String> buildArgs) throws BoostException {
final ArrayList<BuildParam> buildParamsList = new ArrayList<>();
final BuildParam[] buildParams;
if (pullNewerImage) {
buildParamsList.add(BuildParam.pullNewerImage());
}
if (noCache) {
buildParamsList.add(BuildParam.noCache());
}

buildArgs.putAll(dockerizer.getBuildArgs());

try {
final String encodedBuildArgs = URLEncoder.encode(new Gson().toJson(buildArgs), "utf-8");
buildParamsList.add(new BuildParam("buildargs", encodedBuildArgs));
} catch (UnsupportedEncodingException e) {
throw new BoostException("Unable to build image", e);
}

buildParams = buildParamsList.toArray(new BuildParam[buildParamsList.size()]);
return buildParams;
}

/**
* Get the artifact path
*
* @param artifact
* @return the canonical path, if it can be obtained successfully, otherwise the
* absolute path
*/
default String getPathMessageText(File artifact) {
String retVal = null;
try {
if (artifact != null) {
retVal = artifact.getCanonicalPath();
}
} catch (IOException ioexc) {
retVal = artifact.getAbsolutePath();
}
return retVal;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package io.openliberty.boost.docker;
package io.openliberty.boost.common.docker;

import java.text.MessageFormat;

import org.apache.maven.plugin.logging.Log;

import com.spotify.docker.client.ProgressHandler;
import com.spotify.docker.client.exceptions.DockerException;
import com.spotify.docker.client.messages.ProgressMessage;

import io.openliberty.boost.common.BoostLoggerI;

public class DockerLoggingProgressHandler implements ProgressHandler {

private final Log log;
private final BoostLoggerI log;

public DockerLoggingProgressHandler(Log log) {
public DockerLoggingProgressHandler(BoostLoggerI log) {
this.log = log;
}

Expand Down
Loading