From 42077e87d3b84ab88c7c3d7e449fe68909bb0506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Hu=C3=9F?= Date: Thu, 18 Oct 2018 08:09:37 +0200 Subject: [PATCH] chore(build): Refactor BuildService and separate Maven/Docker specific parts. This is part of a larger refactoring story described in #1115. --- pom.xml | 16 +- samples/cargo-jolokia/pom.xml | 4 +- samples/custom-net/pom.xml | 4 +- samples/data-jolokia/pom.xml | 16 +- samples/docker-compose/pom.xml | 4 +- samples/dockerfile/pom.xml | 4 +- samples/dockerignore/pom.xml | 4 +- samples/healthcheck/pom.xml | 4 +- samples/helloworld/pom.xml | 4 +- samples/log/pom.xml | 4 +- samples/multi-wait/pom.xml | 4 +- samples/net/pom.xml | 4 +- samples/pom.xml | 2 +- samples/properties/pom.xml | 4 +- samples/run-java/pom.xml | 4 +- samples/smallest/pom.xml | 4 +- samples/volume/pom.xml | 4 +- samples/zero-config/pom.xml | 4 +- .../docker/AbstractBuildSupportMojo.java | 54 +-- .../maven/docker/AbstractDockerMojo.java | 55 ++- .../io/fabric8/maven/docker/BuildMojo.java | 50 ++- .../io/fabric8/maven/docker/PushMojo.java | 24 +- .../io/fabric8/maven/docker/SourceMojo.java | 16 +- .../io/fabric8/maven/docker/StartMojo.java | 22 +- .../io/fabric8/maven/docker/WatchMojo.java | 8 +- .../docker/access/ecr/EcrExtendedAuth.java | 8 +- .../maven/docker/build/BuildContext.java | 30 ++ .../maven/docker/build/BuildService.java | 15 + .../maven/docker/build/RegistryContext.java | 20 ++ .../maven/docker/build/RegistryService.java | 16 + .../build/docker/DockerBuildService.java | 279 ++++++++++++++++ .../docker}/DockerFileBuilder.java | 10 +- .../docker}/DockerFileKeyword.java | 2 +- .../docker}/DockerFileOption.java | 2 +- .../build/docker/DockerRegistryService.java | 133 ++++++++ .../docker/build/docker/ImagePullCache.java | 81 +++++ .../maven}/AuthConfigFactory.java | 76 ++--- .../maven/MavenArchiveService.java} | 65 ++-- .../docker/build/maven/MavenBuildContext.java | 189 +++++++++++ .../docker/build/maven/MavenCacheBackend.java | 31 ++ .../build/maven/MavenRegistryContext.java | 70 ++++ .../assembly/AllFilesExecCustomizer.java | 2 +- .../maven}/assembly/ArchiverCustomizer.java | 2 +- .../maven}/assembly/AssemblyFiles.java | 2 +- .../{ => build/maven}/assembly/BuildDirs.java | 16 +- .../DockerAssemblyConfigurationSource.java | 34 +- .../assembly/DockerAssemblyManager.java | 147 ++++---- .../maven}/assembly/MappingTrackArchiver.java | 2 +- .../config/BuildImageConfiguration.java | 32 +- .../config/RegistryAuthConfiguration.java | 4 +- .../property/PropertyConfigHandler.java | 4 +- .../handler/property/ValueProvider.java | 5 +- .../maven/docker/model/ContainerDetails.java | 12 +- .../maven/docker/service/BuildService.java | 314 ------------------ .../docker/service/ImagePullManager.java | 114 ------- .../maven/docker/service/RegistryService.java | 228 ------------- .../maven/docker/service/ServiceHub.java | 24 +- .../docker/service/ServiceHubFactory.java | 2 +- .../maven/docker/service/WatchService.java | 136 ++++---- .../docker/util/CredentialHelperClient.java | 8 +- .../maven/docker/util/DockerFileUtil.java | 29 +- .../io/fabric8/maven/docker/util/EnvUtil.java | 85 ++--- .../maven/docker/util/MojoParameters.java | 81 ----- .../DockerBuildServiceTest.java} | 48 ++- .../DockerRegistryServiceTest.java} | 37 +-- .../docker}/DockerFileBuilderTest.java | 26 +- .../maven}/AuthConfigFactoryTest.java | 298 +++++++++-------- ...DockerAssemblyConfigurationSourceTest.java | 53 +-- .../assembly/DockerAssemblyManagerTest.java | 40 ++- .../assembly/MappingTrackArchiverTest.java | 4 +- .../property/PropertyConfigHandlerTest.java | 28 +- .../maven/docker/service/LoadImageTest.java | 30 +- .../maven/docker/util/DockerFileUtilTest.java | 23 +- .../maven}/openshift_nologin_config.yaml | 0 .../maven}/openshift_simple_config.yaml | 0 75 files changed, 1689 insertions(+), 1531 deletions(-) create mode 100644 src/main/java/io/fabric8/maven/docker/build/BuildContext.java create mode 100644 src/main/java/io/fabric8/maven/docker/build/BuildService.java create mode 100644 src/main/java/io/fabric8/maven/docker/build/RegistryContext.java create mode 100644 src/main/java/io/fabric8/maven/docker/build/RegistryService.java create mode 100644 src/main/java/io/fabric8/maven/docker/build/docker/DockerBuildService.java rename src/main/java/io/fabric8/maven/docker/{assembly => build/docker}/DockerFileBuilder.java (97%) rename src/main/java/io/fabric8/maven/docker/{assembly => build/docker}/DockerFileKeyword.java (96%) rename src/main/java/io/fabric8/maven/docker/{assembly => build/docker}/DockerFileOption.java (93%) create mode 100644 src/main/java/io/fabric8/maven/docker/build/docker/DockerRegistryService.java create mode 100644 src/main/java/io/fabric8/maven/docker/build/docker/ImagePullCache.java rename src/main/java/io/fabric8/maven/docker/{util => build/maven}/AuthConfigFactory.java (88%) rename src/main/java/io/fabric8/maven/docker/{service/ArchiveService.java => build/maven/MavenArchiveService.java} (68%) create mode 100644 src/main/java/io/fabric8/maven/docker/build/maven/MavenBuildContext.java create mode 100644 src/main/java/io/fabric8/maven/docker/build/maven/MavenCacheBackend.java create mode 100644 src/main/java/io/fabric8/maven/docker/build/maven/MavenRegistryContext.java rename src/main/java/io/fabric8/maven/docker/{ => build/maven}/assembly/AllFilesExecCustomizer.java (98%) rename src/main/java/io/fabric8/maven/docker/{ => build/maven}/assembly/ArchiverCustomizer.java (94%) rename src/main/java/io/fabric8/maven/docker/{ => build/maven}/assembly/AssemblyFiles.java (98%) rename src/main/java/io/fabric8/maven/docker/{ => build/maven}/assembly/BuildDirs.java (81%) rename src/main/java/io/fabric8/maven/docker/{ => build/maven}/assembly/DockerAssemblyConfigurationSource.java (91%) rename src/main/java/io/fabric8/maven/docker/{ => build/maven}/assembly/DockerAssemblyManager.java (79%) rename src/main/java/io/fabric8/maven/docker/{ => build/maven}/assembly/MappingTrackArchiver.java (99%) delete mode 100644 src/main/java/io/fabric8/maven/docker/service/BuildService.java delete mode 100644 src/main/java/io/fabric8/maven/docker/service/ImagePullManager.java delete mode 100644 src/main/java/io/fabric8/maven/docker/service/RegistryService.java delete mode 100644 src/main/java/io/fabric8/maven/docker/util/MojoParameters.java rename src/test/java/io/fabric8/maven/docker/{service/BuildServiceTest.java => build/DockerBuildServiceTest.java} (73%) rename src/test/java/io/fabric8/maven/docker/{service/RegistryServiceTest.java => build/DockerRegistryServiceTest.java} (86%) rename src/test/java/io/fabric8/maven/docker/{assembly => build/docker}/DockerFileBuilderTest.java (90%) rename src/test/java/io/fabric8/maven/docker/{util => build/maven}/AuthConfigFactoryTest.java (59%) rename src/test/java/io/fabric8/maven/docker/{ => build/maven}/assembly/DockerAssemblyConfigurationSourceTest.java (71%) rename src/test/java/io/fabric8/maven/docker/{ => build/maven}/assembly/DockerAssemblyManagerTest.java (82%) rename src/test/java/io/fabric8/maven/docker/{ => build/maven}/assembly/MappingTrackArchiverTest.java (93%) rename src/test/resources/io/fabric8/maven/docker/{util => build/maven}/openshift_nologin_config.yaml (100%) rename src/test/resources/io/fabric8/maven/docker/{util => build/maven}/openshift_simple_config.yaml (100%) diff --git a/pom.xml b/pom.xml index f582beb84..91991a261 100644 --- a/pom.xml +++ b/pom.xml @@ -35,6 +35,7 @@ UTF-8 3.3.9 + 1.40 @@ -192,7 +193,7 @@ org.jmockit jmockit - 1.40 + ${jmockit.version} test @@ -509,6 +510,18 @@ + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + + -javaagent:${settings.localRepository}/org/jmockit/jmockit/${jmockit.version}/jmockit-${jmockit.version}.jar + + + + @@ -560,7 +573,6 @@ org.apache.maven.plugins maven-surefire-plugin - 2.19.1 diff --git a/samples/cargo-jolokia/pom.xml b/samples/cargo-jolokia/pom.xml index cbb80383d..f429c7bad 100644 --- a/samples/cargo-jolokia/pom.xml +++ b/samples/cargo-jolokia/pom.xml @@ -22,13 +22,13 @@ io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT ../pom.xml io.fabric8 dmp-sample-cargo-jolokia - 0.27.2 + 0.27-SNAPSHOT http://www.jolokia.org diff --git a/samples/custom-net/pom.xml b/samples/custom-net/pom.xml index f424fe779..7543f4b0c 100644 --- a/samples/custom-net/pom.xml +++ b/samples/custom-net/pom.xml @@ -13,12 +13,12 @@ io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT ../pom.xml dmp-custom-net - 0.27.2 + 0.27-SNAPSHOT diff --git a/samples/data-jolokia/pom.xml b/samples/data-jolokia/pom.xml index 459bf40d1..61aa3d3ae 100644 --- a/samples/data-jolokia/pom.xml +++ b/samples/data-jolokia/pom.xml @@ -22,12 +22,12 @@ io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT ../pom.xml dmp-sample-data-jolokia - 0.27.2 + 0.27-SNAPSHOT docker @@ -37,7 +37,7 @@ 8 tomcat docker.io/fabric8/${server.name}-${server.version}:latest - 1.3.2 + 1.3.6 UTF-8 UTF-8 @@ -96,7 +96,6 @@ server ${image} - none data @@ -105,7 +104,7 @@ -Xmx32m - 1 + 1 ${project.basedir}/src/main/docker/environment.properties @@ -169,6 +168,9 @@ assembly.xml + + %a-%t + 5000 both @@ -255,7 +257,7 @@ -Xmx32m - 1 + 1 io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT ../pom.xml diff --git a/samples/net/pom.xml b/samples/net/pom.xml index f0a0bd637..c3e2705fc 100644 --- a/samples/net/pom.xml +++ b/samples/net/pom.xml @@ -16,12 +16,12 @@ io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT ../pom.xml dmp-sample-net - 0.27.2 + 0.27-SNAPSHOT diff --git a/samples/pom.xml b/samples/pom.xml index e5379b668..e8c6a3436 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -21,7 +21,7 @@ io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT pom http://www.jolokia.org diff --git a/samples/properties/pom.xml b/samples/properties/pom.xml index 122d3cad9..5bbec4787 100644 --- a/samples/properties/pom.xml +++ b/samples/properties/pom.xml @@ -10,12 +10,12 @@ io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT ../pom.xml dmp-sample-properties - 0.27.2 + 0.27-SNAPSHOT docker-build diff --git a/samples/run-java/pom.xml b/samples/run-java/pom.xml index fe4366fba..03ff0110a 100644 --- a/samples/run-java/pom.xml +++ b/samples/run-java/pom.xml @@ -7,14 +7,14 @@ io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT ../pom.xml io.fabric8.dmp.samples dmp-sample-run-java jar - 0.27.2 + 0.27-SNAPSHOT diff --git a/samples/smallest/pom.xml b/samples/smallest/pom.xml index 111e9858a..e9e909de9 100644 --- a/samples/smallest/pom.xml +++ b/samples/smallest/pom.xml @@ -4,13 +4,13 @@ io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT ../pom.xml fabric8io dmp-sample-smallest - 0.27.2 + 0.27-SNAPSHOT diff --git a/samples/volume/pom.xml b/samples/volume/pom.xml index 5e9ee091c..19a9e1cbf 100644 --- a/samples/volume/pom.xml +++ b/samples/volume/pom.xml @@ -15,12 +15,12 @@ io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT ../pom.xml dmp-sample-volume - 0.27.2 + 0.27-SNAPSHOT diff --git a/samples/zero-config/pom.xml b/samples/zero-config/pom.xml index a2105f19f..5ea3b5a45 100644 --- a/samples/zero-config/pom.xml +++ b/samples/zero-config/pom.xml @@ -7,7 +7,7 @@ io.fabric8.dmp.samples dmp-sample-parent - 0.27.2 + 0.27-SNAPSHOT ../pom.xml @@ -15,7 +15,7 @@ io.fabric8.dmp.samples demp-sample-zero-config jar - 0.27.2 + 0.27-SNAPSHOT ${project.build.directory}/${project.build.finalName}.jar diff --git a/src/main/java/io/fabric8/maven/docker/AbstractBuildSupportMojo.java b/src/main/java/io/fabric8/maven/docker/AbstractBuildSupportMojo.java index d58514a64..21069c92e 100644 --- a/src/main/java/io/fabric8/maven/docker/AbstractBuildSupportMojo.java +++ b/src/main/java/io/fabric8/maven/docker/AbstractBuildSupportMojo.java @@ -3,10 +3,11 @@ import java.util.List; import java.util.Map; -import io.fabric8.maven.docker.service.BuildService; -import io.fabric8.maven.docker.util.MojoParameters; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; +import io.fabric8.maven.docker.build.maven.MavenRegistryContext; +import io.fabric8.maven.docker.config.ImagePullPolicy; +import io.fabric8.maven.docker.build.maven.MavenArchiveService; import org.apache.maven.archiver.MavenArchiveConfiguration; -import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; @@ -25,41 +26,50 @@ abstract public class AbstractBuildSupportMojo extends AbstractDockerMojo { // See also here: http://maven.40175.n5.nabble.com/Mojo-Java-1-5-Component-MavenProject-returns-null-vs-JavaDoc-parameter-expression-quot-project-quot-s-td5733805.html @Parameter - private MavenArchiveConfiguration archive; + protected MavenArchiveConfiguration archive; @Component - private MavenFileFilter mavenFileFilter; + protected MavenFileFilter mavenFileFilter; @Component - private MavenReaderFilter mavenFilterReader; + protected MavenReaderFilter mavenReaderFilter; @Parameter - private Map buildArgs; + protected Map buildArgs; @Parameter(property = "docker.pull.registry") - private String pullRegistry; + protected String pullRegistry; @Parameter(property = "docker.source.dir", defaultValue="src/main/docker") - private String sourceDirectory; + protected String sourceDirectory; @Parameter(property = "docker.target.dir", defaultValue="target/docker") - private String outputDirectory; + protected String outputDirectory; @Parameter( defaultValue = "${reactorProjects}", required = true, readonly = true ) - private List reactorProjects; + protected List reactorProjects; - protected BuildService.BuildContext getBuildContext() throws MojoExecutionException { - return new BuildService.BuildContext.Builder() - .buildArgs(buildArgs) - .mojoParameters(createMojoParameters()) - .registryConfig(getRegistryConfig(pullRegistry)) - .build(); - } + protected MavenBuildContext getBuildContext(MavenArchiveService archiveService) { - protected MojoParameters createMojoParameters() { - return new MojoParameters(session, project, archive, mavenFileFilter, mavenFilterReader, - settings, sourceDirectory, outputDirectory, reactorProjects); - } + MavenRegistryContext registryContext = new MavenRegistryContext.Builder() + .authConfigFactory(authConfigFactory) + .defaultImagePullPolicy(imagePullPolicy != null ? ImagePullPolicy.fromString(imagePullPolicy) : null) + .pullRegistry(pullRegistry) + .build(); + return new MavenBuildContext.Builder() + .project(project) + .sourceDirectory(sourceDirectory) + .outputDirectory(outputDirectory) + .session(session) + .settings(settings) + .mavenFileFilter(mavenFileFilter) + .mavenReaderFilter(mavenReaderFilter) + .reactorProjects(reactorProjects) + .archiveConfiguration(archive) + .archiveService(archiveService) + .registryContext(registryContext) + .build(); + } } diff --git a/src/main/java/io/fabric8/maven/docker/AbstractDockerMojo.java b/src/main/java/io/fabric8/maven/docker/AbstractDockerMojo.java index 012457dbf..72a436393 100644 --- a/src/main/java/io/fabric8/maven/docker/AbstractDockerMojo.java +++ b/src/main/java/io/fabric8/maven/docker/AbstractDockerMojo.java @@ -3,11 +3,13 @@ import java.io.File; import java.io.IOException; import java.util.Date; +import java.util.HashMap; import java.util.List; -import java.util.Properties; +import java.util.Map; import io.fabric8.maven.docker.access.DockerAccess; import io.fabric8.maven.docker.access.ExecException; +import io.fabric8.maven.docker.build.maven.MavenCacheBackend; import io.fabric8.maven.docker.config.BuildImageConfiguration; import io.fabric8.maven.docker.config.ConfigHelper; import io.fabric8.maven.docker.config.DockerMachineConfiguration; @@ -18,12 +20,11 @@ import io.fabric8.maven.docker.log.LogDispatcher; import io.fabric8.maven.docker.log.LogOutputSpecFactory; import io.fabric8.maven.docker.service.DockerAccessFactory; -import io.fabric8.maven.docker.service.ImagePullManager; -import io.fabric8.maven.docker.service.RegistryService; +import io.fabric8.maven.docker.build.docker.ImagePullCache; import io.fabric8.maven.docker.service.ServiceHub; import io.fabric8.maven.docker.service.ServiceHubFactory; import io.fabric8.maven.docker.util.AnsiLogger; -import io.fabric8.maven.docker.util.AuthConfigFactory; +import io.fabric8.maven.docker.build.maven.AuthConfigFactory; import io.fabric8.maven.docker.util.EnvUtil; import io.fabric8.maven.docker.util.GavLabel; import io.fabric8.maven.docker.util.ImageNameFormatter; @@ -187,8 +188,11 @@ public abstract class AbstractDockerMojo extends AbstractMojo implements Context // mangle the image configurations. private List resolvedImages; + // will be initialized and remembered for creating the authconfigfactory later + private PlexusContainer plexusContainer; + // Handler dealing with authentication credentials - private AuthConfigFactory authConfigFactory; + protected AuthConfigFactory authConfigFactory; protected Logger log; @@ -206,7 +210,7 @@ public abstract class AbstractDockerMojo extends AbstractMojo implements Context public void execute() throws MojoExecutionException, MojoFailureException { if (!skip) { log = new AnsiLogger(getLog(), useColor, verbose, !settings.getInteractiveMode(), getLogPrefix()); - authConfigFactory.setLog(log); + authConfigFactory = new AuthConfigFactory(plexusContainer, settings, getRegistryAuthConfig(), registry, log); imageConfigResolver.setLog(log); LogOutputSpecFactory logSpecFactory = new LogOutputSpecFactory(useColor, logStdout, logDate); @@ -258,14 +262,15 @@ protected DockerAccessFactory.DockerAccessContext getDockerAccessContext() { .build(); } - protected RegistryService.RegistryConfig getRegistryConfig(String specificRegistry) throws MojoExecutionException { - return new RegistryService.RegistryConfig.Builder() - .settings(settings) - .authConfig(authConfig != null ? authConfig.toMap() : null) - .authConfigFactory(authConfigFactory) - .skipExtendedAuth(skipExtendedAuth) - .registry(specificRegistry != null ? specificRegistry : registry) - .build(); + protected Map getRegistryAuthConfig() { + Map registryAuthConfig = new HashMap(); + if (authConfig != null) { + registryAuthConfig.putAll(authConfig.toMap()); + } + if (skipExtendedAuth) { + registryAuthConfig.put(AuthConfigFactory.SKIP_EXTENDED_AUTH, true); + } + return registryAuthConfig; } /** @@ -381,7 +386,7 @@ protected List getVolumes() { @Override public void contextualize(Context context) throws ContextException { - authConfigFactory = new AuthConfigFactory((PlexusContainer) context.get(PlexusConstants.PLEXUS_KEY)); + plexusContainer = (PlexusContainer) context.get(PlexusConstants.PLEXUS_KEY); } // ================================================================================= @@ -400,24 +405,8 @@ protected LogDispatcher getLogDispatcher(ServiceHub hub) { return dispatcher; } - public ImagePullManager getImagePullManager(String imagePullPolicy, String autoPull) { - return new ImagePullManager(getSessionCacheStore(), imagePullPolicy, autoPull); - } - - private ImagePullManager.CacheStore getSessionCacheStore() { - return new ImagePullManager.CacheStore() { - @Override - public String get(String key) { - Properties userProperties = session.getUserProperties(); - return userProperties.getProperty(key); - } - - @Override - public void put(String key, String value) { - Properties userProperties = session.getUserProperties(); - userProperties.setProperty(key, value); - } - }; + public ImagePullCache getImagePullManager() { + return new ImagePullCache(new MavenCacheBackend(session)); } private ImageConfiguration createSimpleDockerfileConfig(File dockerFile) { diff --git a/src/main/java/io/fabric8/maven/docker/BuildMojo.java b/src/main/java/io/fabric8/maven/docker/BuildMojo.java index 4db8b6583..851492ab2 100644 --- a/src/main/java/io/fabric8/maven/docker/BuildMojo.java +++ b/src/main/java/io/fabric8/maven/docker/BuildMojo.java @@ -11,10 +11,10 @@ import java.util.Enumeration; import io.fabric8.maven.docker.access.DockerAccessException; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import io.fabric8.maven.docker.config.BuildImageConfiguration; import io.fabric8.maven.docker.config.ImageConfiguration; -import io.fabric8.maven.docker.service.BuildService; -import io.fabric8.maven.docker.service.ImagePullManager; +import io.fabric8.maven.docker.build.docker.DockerBuildService; import io.fabric8.maven.docker.service.ServiceHub; import io.fabric8.maven.docker.util.EnvUtil; import org.apache.maven.plugin.MojoExecutionException; @@ -61,31 +61,6 @@ protected void executeInternal(ServiceHub hub) throws IOException, MojoExecution } } - protected void buildAndTag(ServiceHub hub, ImageConfiguration imageConfig) - throws MojoExecutionException, IOException { - - EnvUtil.storeTimestamp(getBuildTimestampFile(), getBuildTimestamp()); - - BuildService.BuildContext buildContext = getBuildContext(); - ImagePullManager pullManager = getImagePullManager(determinePullPolicy(imageConfig.getBuildConfiguration()), autoPull); - BuildService buildService = hub.getBuildService(); - - buildService.buildImage(imageConfig, pullManager, buildContext); - if (!skipTag) { - buildService.tagImage(imageConfig.getName(), imageConfig); - } - } - - // We ignore an already existing date file and always return the current date - - @Override - protected Date getReferenceDate() { - return new Date(); - } - private String determinePullPolicy(BuildImageConfiguration buildConfig) { - return buildConfig != null && buildConfig.getImagePullPolicy() != null ? buildConfig.getImagePullPolicy() : imagePullPolicy; - } - /** * Helper method to process an ImageConfiguration. * @@ -106,6 +81,27 @@ private void processImageConfig(ServiceHub hub, ImageConfiguration aImageConfig) } } + protected void buildAndTag(ServiceHub hub, ImageConfiguration imageConfig) + throws MojoExecutionException, IOException { + + EnvUtil.storeTimestamp(getBuildTimestampFile(), getBuildTimestamp()); + + MavenBuildContext buildContext = getBuildContext(hub.getArchiveService()); + DockerBuildService buildService = hub.getBuildService(); + + buildService.buildImage(imageConfig, buildContext, buildArgs); + if (!skipTag) { + buildService.tagImage(imageConfig.getName(), imageConfig); + } + } + + // We ignore an already existing date file and always return the current date + @Override + protected Date getReferenceDate() { + return new Date(); + } + + // check for a run-java.sh dependency an extract the script to target/ if found private void executeBuildPlugins() { try { diff --git a/src/main/java/io/fabric8/maven/docker/PushMojo.java b/src/main/java/io/fabric8/maven/docker/PushMojo.java index 07f38ed55..6c4640536 100644 --- a/src/main/java/io/fabric8/maven/docker/PushMojo.java +++ b/src/main/java/io/fabric8/maven/docker/PushMojo.java @@ -1,9 +1,10 @@ package io.fabric8.maven.docker; -import io.fabric8.maven.docker.access.DockerAccessException; -import io.fabric8.maven.docker.service.ServiceHub; +import java.io.IOException; -import org.apache.maven.plugin.MojoExecutionException; +import io.fabric8.maven.docker.build.maven.MavenRegistryContext; +import io.fabric8.maven.docker.config.ImageConfiguration; +import io.fabric8.maven.docker.service.ServiceHub; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; @@ -22,13 +23,13 @@ public class PushMojo extends AbstractDockerMojo { @Parameter(property = "docker.skip.push", defaultValue = "false") private boolean skipPush; - - /** + + /** * Skip building tags */ @Parameter(property = "docker.skip.tag", defaultValue = "false") private boolean skipTag; - + @Parameter(property = "docker.push.retries", defaultValue = "0") private int retries; @@ -36,11 +37,18 @@ public class PushMojo extends AbstractDockerMojo { * {@inheritDoc} */ @Override - public void executeInternal(ServiceHub hub) throws DockerAccessException, MojoExecutionException { + public void executeInternal(ServiceHub hub) throws IOException { if (skipPush) { return; } - hub.getRegistryService().pushImages(getResolvedImages(), retries, getRegistryConfig(pushRegistry), skipTag); + MavenRegistryContext registryContext = new MavenRegistryContext.Builder() + .authConfigFactory(authConfigFactory) + .pushRegistry(pushRegistry) + .build(); + + for (ImageConfiguration imageConfig : getResolvedImages()) { + hub.getRegistryService().pushImage(imageConfig, retries, skipTag, registryContext); + } } } diff --git a/src/main/java/io/fabric8/maven/docker/SourceMojo.java b/src/main/java/io/fabric8/maven/docker/SourceMojo.java index c6acad3eb..f1c54106f 100644 --- a/src/main/java/io/fabric8/maven/docker/SourceMojo.java +++ b/src/main/java/io/fabric8/maven/docker/SourceMojo.java @@ -17,17 +17,15 @@ */ import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; -import io.fabric8.maven.docker.access.DockerAccessException; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import io.fabric8.maven.docker.config.BuildImageConfiguration; -import io.fabric8.maven.docker.config.ImageConfiguration; import io.fabric8.maven.docker.config.BuildImageSelectMode; +import io.fabric8.maven.docker.config.ImageConfiguration; import io.fabric8.maven.docker.service.ServiceHub; -import io.fabric8.maven.docker.util.MojoParameters; - -import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; @@ -65,8 +63,8 @@ public class SourceMojo extends AbstractBuildSupportMojo { private BuildImageSelectMode sourceMode = BuildImageSelectMode.first; @Override - protected void executeInternal(ServiceHub hub) throws DockerAccessException, MojoExecutionException { - MojoParameters params = createMojoParameters(); + protected void executeInternal(ServiceHub hub) throws IOException { + MavenBuildContext context = getBuildContext(hub.getArchiveService()); List imageConfigs = new ArrayList<>(); for (ImageConfiguration imageConfig : getResolvedImages()) { BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); @@ -80,12 +78,12 @@ protected void executeInternal(ServiceHub hub) throws DockerAccessException, Moj } if (sourceMode == BuildImageSelectMode.first && imageConfigs.size() > 0) { ImageConfiguration imageConfig = imageConfigs.get(0); - File dockerTar = hub.getArchiveService().createDockerBuildArchive(imageConfig, params); + File dockerTar = hub.getArchiveService().createDockerBuildArchive(imageConfig, context); projectHelper.attachArtifact(project, getArchiveType(imageConfig), getClassifier(null), dockerTar); } else { for (ImageConfiguration imageConfig : imageConfigs) { - File dockerTar = hub.getArchiveService().createDockerBuildArchive(imageConfig, params); + File dockerTar = hub.getArchiveService().createDockerBuildArchive(imageConfig, context); String alias = imageConfig.getAlias(); if (alias == null) { throw new IllegalArgumentException( diff --git a/src/main/java/io/fabric8/maven/docker/StartMojo.java b/src/main/java/io/fabric8/maven/docker/StartMojo.java index 1125cb47a..78bd42707 100644 --- a/src/main/java/io/fabric8/maven/docker/StartMojo.java +++ b/src/main/java/io/fabric8/maven/docker/StartMojo.java @@ -29,16 +29,17 @@ import io.fabric8.maven.docker.access.DockerAccessException; import io.fabric8.maven.docker.access.ExecException; import io.fabric8.maven.docker.access.PortMapping; +import io.fabric8.maven.docker.build.maven.MavenRegistryContext; +import io.fabric8.maven.docker.build.RegistryContext; import io.fabric8.maven.docker.config.ImageConfiguration; +import io.fabric8.maven.docker.config.ImagePullPolicy; import io.fabric8.maven.docker.config.NetworkConfig; import io.fabric8.maven.docker.config.RunImageConfiguration; import io.fabric8.maven.docker.config.RunVolumeConfiguration; import io.fabric8.maven.docker.config.VolumeConfiguration; import io.fabric8.maven.docker.log.LogDispatcher; import io.fabric8.maven.docker.model.Container; -import io.fabric8.maven.docker.service.ImagePullManager; import io.fabric8.maven.docker.service.QueryService; -import io.fabric8.maven.docker.service.RegistryService; import io.fabric8.maven.docker.service.RunService; import io.fabric8.maven.docker.service.ServiceHub; import io.fabric8.maven.docker.service.helper.StartContainerExecutor; @@ -330,7 +331,7 @@ private List getImagesWhoseDependenciesHasStarted(Queue prepareStart(ServiceHub hub, QueryService queryService, RunService runService, Set imageAliases) - throws DockerAccessException, MojoExecutionException { + throws DockerAccessException { final Queue imagesWaitingToStart = new ArrayDeque<>(); for (StartOrderResolver.Resolvable resolvable : runService.getImagesConfigsInOrder(queryService, getResolvedImages())) { final ImageConfiguration imageConfig = (ImageConfiguration) resolvable; @@ -339,11 +340,14 @@ private Queue prepareStart(ServiceHub hub, QueryService quer //String imageName = new ImageName(imageConfig.getName()).getFullNameWithTag(registry); RunImageConfiguration runConfig = imageConfig.getRunConfiguration(); - RegistryService.RegistryConfig registryConfig = getRegistryConfig(pullRegistry); - ImagePullManager pullManager = getImagePullManager(determinePullPolicy(runConfig), autoPull); + String policyS = runConfig.getImagePullPolicy() != null ? runConfig.getImagePullPolicy() : this.imagePullPolicy; + ImagePullPolicy policy = policyS != null ? ImagePullPolicy.fromString(policyS) : ImagePullPolicy.IfNotPresent; - hub.getRegistryService().pullImageWithPolicy(imageConfig.getName(), pullManager, registryConfig, - queryService.hasImage(imageConfig.getName())); + RegistryContext registryContext = new MavenRegistryContext.Builder() + .pullRegistry(pullRegistry) + .authConfigFactory(authConfigFactory) + .build(); + hub.getRegistryService().pullImage(imageConfig.getName(), policy, registryContext); NetworkConfig config = runConfig.getNetworkingConfig(); List bindMounts = extractBindMounts(runConfig.getVolumeConfiguration()); @@ -367,10 +371,6 @@ private List extractBindMounts(RunVolumeConfiguration volumeConfiguratio return volumeConfiguration.getBind() != null ? volumeConfiguration.getBind() : Collections.emptyList(); } - private String determinePullPolicy(RunImageConfiguration runConfig) { - return runConfig.getImagePullPolicy() != null ? runConfig.getImagePullPolicy() : imagePullPolicy; - } - private List filterOutNonAliases(Set imageAliases, List dependencies) { List ret = new ArrayList<>(); for (String alias : dependencies) { diff --git a/src/main/java/io/fabric8/maven/docker/WatchMojo.java b/src/main/java/io/fabric8/maven/docker/WatchMojo.java index 04d4c0d64..5acd9850d 100644 --- a/src/main/java/io/fabric8/maven/docker/WatchMojo.java +++ b/src/main/java/io/fabric8/maven/docker/WatchMojo.java @@ -17,8 +17,8 @@ import java.io.IOException; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import io.fabric8.maven.docker.config.WatchMode; -import io.fabric8.maven.docker.service.BuildService; import io.fabric8.maven.docker.service.ServiceHub; import io.fabric8.maven.docker.service.WatchService; import io.fabric8.maven.docker.util.ContainerNamingUtil; @@ -77,7 +77,7 @@ public class WatchMojo extends AbstractBuildSupportMojo { protected synchronized void executeInternal(ServiceHub hub) throws IOException, MojoExecutionException { - BuildService.BuildContext buildContext = getBuildContext(); + MavenBuildContext buildContext = getBuildContext(hub.getArchiveService()); WatchService.WatchContext watchContext = getWatchContext(hub); hub.getWatchService().watch(watchContext, buildContext, getResolvedImages()); @@ -94,12 +94,14 @@ protected WatchService.WatchContext getWatchContext(ServiceHub hub) throws IOExc .keepRunning(keepRunning) .removeVolumes(removeVolumes) .containerNamePattern(containerNamePattern) + .buildArgs(buildArgs) .buildTimestamp(getBuildTimestamp()) .pomLabel(getGavLabel()) - .mojoParameters(createMojoParameters()) .follow(follow()) .showLogs(showLogs()) .serviceHubFactory(serviceHubFactory) + .properties(project.getProperties()) + .basedir(project.getBasedir()) .hub(hub) .dispatcher(getLogDispatcher(hub)) .build(); diff --git a/src/main/java/io/fabric8/maven/docker/access/ecr/EcrExtendedAuth.java b/src/main/java/io/fabric8/maven/docker/access/ecr/EcrExtendedAuth.java index 03791aa95..1b2a6201a 100644 --- a/src/main/java/io/fabric8/maven/docker/access/ecr/EcrExtendedAuth.java +++ b/src/main/java/io/fabric8/maven/docker/access/ecr/EcrExtendedAuth.java @@ -76,7 +76,7 @@ public boolean isAwsRegistry() { * @throws IOException * @throws MojoExecutionException */ - public AuthConfig extendedAuth(AuthConfig localCredentials) throws IOException, MojoExecutionException { + public AuthConfig extendedAuth(AuthConfig localCredentials) throws IOException { JsonObject jo = getAuthorizationToken(localCredentials); JsonArray authorizationDatas = jo.getAsJsonArray("authorizationData"); @@ -86,7 +86,7 @@ public AuthConfig extendedAuth(AuthConfig localCredentials) throws IOException, return new AuthConfig(authorizationToken, "none"); } - private JsonObject getAuthorizationToken(AuthConfig localCredentials) throws IOException, MojoExecutionException { + private JsonObject getAuthorizationToken(AuthConfig localCredentials) throws IOException { HttpPost request = createSignedRequest(localCredentials, new Date()); return executeRequest(createClient(), request); } @@ -95,13 +95,13 @@ CloseableHttpClient createClient() { return HttpClients.custom().useSystemProperties().build(); } - private JsonObject executeRequest(CloseableHttpClient client, HttpPost request) throws IOException, MojoExecutionException { + private JsonObject executeRequest(CloseableHttpClient client, HttpPost request) throws IOException { try { CloseableHttpResponse response = client.execute(request); int statusCode = response.getStatusLine().getStatusCode(); logger.debug("Response status %d", statusCode); if (statusCode != HttpStatus.SC_OK) { - throw new MojoExecutionException("AWS authentication failure"); + throw new SecurityException("AWS authentication failure"); } HttpEntity entity = response.getEntity(); diff --git a/src/main/java/io/fabric8/maven/docker/build/BuildContext.java b/src/main/java/io/fabric8/maven/docker/build/BuildContext.java new file mode 100644 index 000000000..f6586531b --- /dev/null +++ b/src/main/java/io/fabric8/maven/docker/build/BuildContext.java @@ -0,0 +1,30 @@ +package io.fabric8.maven.docker.build; + +import java.io.File; +import java.io.IOException; +import java.util.Properties; +import java.util.function.Function; + +import io.fabric8.maven.docker.config.BuildImageConfiguration; +import io.fabric8.maven.docker.util.Logger; + +/** + * @author roland + * @since 16.10.18 + */ +public interface BuildContext { + + String getSourceDirectory(); + + File getBasedir(); + + String getOutputDirectory(); + + Properties getProperties(); + + Function createInterpolator(String filter); + + File createImageContentArchive(String imageName, BuildImageConfiguration buildConfig, Logger log) throws IOException; + + RegistryContext getRegistryContext(); +} diff --git a/src/main/java/io/fabric8/maven/docker/build/BuildService.java b/src/main/java/io/fabric8/maven/docker/build/BuildService.java new file mode 100644 index 000000000..c04ad2f2d --- /dev/null +++ b/src/main/java/io/fabric8/maven/docker/build/BuildService.java @@ -0,0 +1,15 @@ +package io.fabric8.maven.docker.build; + +import java.io.IOException; +import java.util.Map; + +import io.fabric8.maven.docker.config.ImageConfiguration; + +/** + * @author roland + * @since 16.10.18 + */ +public interface BuildService { + void buildImage(ImageConfiguration imageConfig, BuildContext buildContext, Map buildArgs) + throws IOException; +} diff --git a/src/main/java/io/fabric8/maven/docker/build/RegistryContext.java b/src/main/java/io/fabric8/maven/docker/build/RegistryContext.java new file mode 100644 index 000000000..a738821de --- /dev/null +++ b/src/main/java/io/fabric8/maven/docker/build/RegistryContext.java @@ -0,0 +1,20 @@ +package io.fabric8.maven.docker.build; + +import io.fabric8.maven.docker.access.AuthConfig; +import io.fabric8.maven.docker.config.ImagePullPolicy; + +/** + * @author roland + * @since 17.10.18 + */ +public interface RegistryContext { + + ImagePullPolicy getDefaultImagePullPolicy(); + + String getPushRegistry(); + + String getPullRegistry(); + + AuthConfig lookupRegistryAuthConfig(boolean isPush, String user, String registry); + +} diff --git a/src/main/java/io/fabric8/maven/docker/build/RegistryService.java b/src/main/java/io/fabric8/maven/docker/build/RegistryService.java new file mode 100644 index 000000000..6d42bdf1a --- /dev/null +++ b/src/main/java/io/fabric8/maven/docker/build/RegistryService.java @@ -0,0 +1,16 @@ +package io.fabric8.maven.docker.build; + +import java.io.IOException; + +import io.fabric8.maven.docker.config.ImageConfiguration; +import io.fabric8.maven.docker.config.ImagePullPolicy; + +/** + * @author roland + * @since 17.10.18 + */ +public interface RegistryService { + void pushImage(ImageConfiguration imageConfig, int retries, boolean skipTag, RegistryContext registryContext) throws IOException; + + void pullImage(String image, ImagePullPolicy policy, RegistryContext registryContext) throws IOException; +} diff --git a/src/main/java/io/fabric8/maven/docker/build/docker/DockerBuildService.java b/src/main/java/io/fabric8/maven/docker/build/docker/DockerBuildService.java new file mode 100644 index 000000000..98641214f --- /dev/null +++ b/src/main/java/io/fabric8/maven/docker/build/docker/DockerBuildService.java @@ -0,0 +1,279 @@ +package io.fabric8.maven.docker.build.docker; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Properties; + +import com.google.common.collect.ImmutableMap; +import io.fabric8.maven.docker.access.BuildOptions; +import io.fabric8.maven.docker.access.DockerAccess; +import io.fabric8.maven.docker.access.DockerAccessException; +import io.fabric8.maven.docker.build.maven.assembly.DockerAssemblyManager; +import io.fabric8.maven.docker.build.BuildContext; +import io.fabric8.maven.docker.build.BuildService; +import io.fabric8.maven.docker.build.RegistryService; +import io.fabric8.maven.docker.config.AssemblyConfiguration; +import io.fabric8.maven.docker.config.BuildImageConfiguration; +import io.fabric8.maven.docker.config.CleanupMode; +import io.fabric8.maven.docker.config.ImageConfiguration; +import io.fabric8.maven.docker.config.ImagePullPolicy; +import io.fabric8.maven.docker.util.DockerFileUtil; +import io.fabric8.maven.docker.util.EnvUtil; +import io.fabric8.maven.docker.util.ImageName; +import io.fabric8.maven.docker.util.Logger; + +public class DockerBuildService implements BuildService { + + private final DockerAccess docker; + private final RegistryService registryService; + private final Logger log; + + public DockerBuildService(DockerAccess docker, RegistryService registryService, Logger log) { + this.docker = docker; + this.registryService = registryService; + this.log = log; + } + + /** + * Pull the base image if needed and run the build. + * + * @param imageConfig the image configuration + * @param buildContext the build context + */ + @Override + public void buildImage(ImageConfiguration imageConfig, BuildContext buildContext, Map buildArgs) + throws IOException { + // Call a pre-hook to the build + autoPullBaseImageIfRequested(imageConfig, buildContext); + + String imageName = imageConfig.getName(); + ImageName.validate(imageName); + BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); + + // Load an archive if present + if (buildConfig.getDockerArchive() != null) { + loadImageFromArchive(imageName, buildContext, buildConfig.getDockerArchive()); + return; + } + + // Get old image id (if requested + Optional oldImageId = getOldImageId(imageName, buildConfig); + + // Create an archive usable for sending to the Docker daemon + File dockerArchive = createDockerContextArchive(imageConfig, buildContext); + + // Prepare options for building against a Docker daemon and do the build + String newImageId = build(imageConfig, buildArgs, dockerArchive); + + // Remove the image if requested + if (oldImageId.isPresent() && !oldImageId.get().equals(newImageId)) { + removeOldImage(imageConfig, oldImageId.get()); + } + } + + public void tagImage(String imageName, ImageConfiguration imageConfig) throws DockerAccessException { + List tags = imageConfig.getBuildConfiguration().getTags(); + if (tags.size() > 0) { + log.info("%s: Tag with %s", imageConfig.getDescription(), EnvUtil.stringJoin(tags, ",")); + + for (String tag : tags) { + if (tag != null) { + docker.tag(imageName, new ImageName(imageName, tag).getFullName(), true); + } + } + + log.debug("Tagging image successful!"); + } + } + + + private void autoPullBaseImageIfRequested(ImageConfiguration imageConfig, BuildContext buildContext) throws IOException { + BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); + + if (buildConfig.getDockerArchive() != null) { + // No auto pull needed in archive mode + return; + } + + String fromImage; + if (buildConfig.isDockerFileMode()) { + fromImage = extractBaseFromDockerfile(buildConfig, buildContext); + } else { + fromImage = extractBaseFromConfiguration(buildConfig); + } + if (fromImage != null && !"scratch".equals(fromImage)) { + + ImagePullPolicy imagePullPolicy = + buildConfig.getImagePullPolicy() != null ? + createPullPolicy(buildConfig.getImagePullPolicy()) : + buildContext.getRegistryContext().getDefaultImagePullPolicy(); + + registryService.pullImage(fromImage, imagePullPolicy, buildContext.getRegistryContext()); + } + } + + private ImagePullPolicy createPullPolicy(String imagePullPolicy) { + if (imagePullPolicy != null) { + return ImagePullPolicy.fromString(imagePullPolicy); + } + return ImagePullPolicy.IfNotPresent; + } + + + private String extractBaseFromConfiguration(BuildImageConfiguration buildConfig) { + String fromImage; + fromImage = buildConfig.getFrom(); + if (fromImage == null) { + AssemblyConfiguration assemblyConfig = buildConfig.getAssemblyConfiguration(); + if (assemblyConfig == null) { + fromImage = DockerAssemblyManager.DEFAULT_DATA_BASE_IMAGE; + } + } + return fromImage; + } + + private String extractBaseFromDockerfile(BuildImageConfiguration buildConfig, BuildContext ctx) { + String fromImage; + try { + final File fullDockerFilePath = + EnvUtil.prepareAbsoluteSourceDirPath(ctx, buildConfig.getDockerFile().getPath()); + fromImage = DockerFileUtil.extractBaseImage( + fullDockerFilePath, + ctx.createInterpolator(buildConfig.getFilter())); + + } catch (IOException e) { + // Cant extract base image, so we wont try an auto pull. An error will occur later anyway when + // building the image, so we are passive here. + fromImage = null; + } + return fromImage; + } + + + private void loadImageFromArchive(String imageName, BuildContext ctx, File dockerArchive) throws DockerAccessException { + long time = System.currentTimeMillis(); + File dockerArchiveAbsolute = EnvUtil.prepareAbsoluteSourceDirPath(ctx, dockerArchive.getPath()); + docker.loadImage(imageName, dockerArchiveAbsolute); + log.info("%s: Loaded tarball in %s", dockerArchive, EnvUtil.formatDurationTill(time)); + } + + private File createDockerContextArchive(ImageConfiguration imageConfig, BuildContext ctx) throws IOException { + long time = System.currentTimeMillis(); + String imageName = imageConfig.getName(); + BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); + File dockerContextArchive = ctx.createImageContentArchive(imageName, buildConfig, log); + log.info("%s: Created %s in %s", + imageConfig.getDescription(), + dockerContextArchive.getName(), + EnvUtil.formatDurationTill(time)); + return dockerContextArchive; + } + + private Optional getOldImageId(String imageName, BuildImageConfiguration buildConfig) throws DockerAccessException { + CleanupMode cleanupMode = CleanupMode.parse(buildConfig.getCleanupMode()); + return cleanupMode.isRemove() ? + Optional.ofNullable(docker.getImageId(imageName)) : + Optional.empty(); + } + + private String build(ImageConfiguration imageConfig, + Map buildArgs, + File dockerArchive) throws DockerAccessException { + String imageName = imageConfig.getName(); + BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); + boolean noCache = checkForNocache(imageConfig); + BuildOptions opts = + new BuildOptions(buildConfig.getBuildOptions()) + .dockerfile(getDockerfileName(buildConfig)) + .forceRemove(CleanupMode.parse(buildConfig.getCleanupMode()).isRemove()) + .noCache(noCache) + .buildArgs(prepareBuildArgs(buildArgs, buildConfig)); + docker.buildImage(imageName, dockerArchive, opts); + String newImageId = docker.getImageId(imageName); + log.info("%s: Built image %s", imageConfig.getDescription(), newImageId); + return newImageId; + } + + private void removeOldImage(ImageConfiguration imageConfig, String oldImageId) throws DockerAccessException { + try { + docker.removeImage(oldImageId, true); + log.info("%s: Removed old image %s", imageConfig.getDescription(), oldImageId); + } catch (DockerAccessException exp) { + String cleanup = imageConfig.getBuildConfiguration().getCleanupMode(); + if (CleanupMode.parse(cleanup) == CleanupMode.TRY_TO_REMOVE) { + log.warn("%s: %s (old image)%s", imageConfig.getDescription(), exp.getMessage(), + (exp.getCause() != null ? " [" + exp.getCause().getMessage() + "]" : "")); + } else { + throw exp; + } + } + } + + private Map prepareBuildArgs(Map buildArgs, BuildImageConfiguration buildConfig) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + if (buildArgs != null) { + builder.putAll(buildArgs); + } + if (buildConfig.getArgs() != null) { + builder.putAll(buildConfig.getArgs()); + } + return builder.build(); + } + + private String getDockerfileName(BuildImageConfiguration buildConfig) { + if (buildConfig.isDockerFileMode()) { + return buildConfig.getDockerFile().getName(); + } else { + return null; + } + } + + private Map addBuildArgs(BuildContext buildContext, Map buildArgs) { + Map buildArgsFromProject = addBuildArgsFromProperties(buildContext.getProperties()); + Map buildArgsFromSystem = addBuildArgsFromProperties(System.getProperties()); + return ImmutableMap.builder() + .putAll(Optional.of(buildArgs).orElse(Collections.emptyMap())) + .putAll(buildArgsFromProject) + .putAll(buildArgsFromSystem) + .build(); + } + + private Map addBuildArgsFromProperties(Properties properties) { + String argPrefix = "docker.buildArg."; + Map buildArgs = new HashMap<>(); + for (Object keyObj : properties.keySet()) { + String key = (String) keyObj; + if (key.startsWith(argPrefix)) { + String argKey = key.replaceFirst(argPrefix, ""); + String value = properties.getProperty(key); + + if (!isEmpty(value)) { + buildArgs.put(argKey, value); + } + } + } + log.debug("Build args set %s", buildArgs); + return buildArgs; + } + + + + private boolean checkForNocache(ImageConfiguration imageConfig) { + String nocache = System.getProperty("docker.nocache"); + if (nocache != null) { + return nocache.length() == 0 || Boolean.valueOf(nocache); + } else { + BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); + return buildConfig.nocache(); + } + } + + private boolean isEmpty(String str) { + return str == null || str.isEmpty(); + } +} diff --git a/src/main/java/io/fabric8/maven/docker/assembly/DockerFileBuilder.java b/src/main/java/io/fabric8/maven/docker/build/docker/DockerFileBuilder.java similarity index 97% rename from src/main/java/io/fabric8/maven/docker/assembly/DockerFileBuilder.java rename to src/main/java/io/fabric8/maven/docker/build/docker/DockerFileBuilder.java index c14243923..75110bbc9 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/DockerFileBuilder.java +++ b/src/main/java/io/fabric8/maven/docker/build/docker/DockerFileBuilder.java @@ -1,17 +1,19 @@ -package io.fabric8.maven.docker.assembly; +package io.fabric8.maven.docker.build.docker; import java.io.File; import java.io.IOException; +import java.nio.charset.Charset; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.google.common.base.Joiner; +import io.fabric8.maven.docker.build.maven.assembly.DockerAssemblyManager; import io.fabric8.maven.docker.config.Arguments; import io.fabric8.maven.docker.config.HealthCheckConfiguration; -import org.codehaus.plexus.util.FileUtils; -import org.codehaus.plexus.util.StringUtils; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; /** * Create a dockerfile @@ -79,7 +81,7 @@ public class DockerFileBuilder { */ public File write(File destDir) throws IOException { File target = new File(destDir,"Dockerfile"); - FileUtils.fileWrite(target, content()); + FileUtils.write(target, content(), Charset.defaultCharset()); return target; } diff --git a/src/main/java/io/fabric8/maven/docker/assembly/DockerFileKeyword.java b/src/main/java/io/fabric8/maven/docker/build/docker/DockerFileKeyword.java similarity index 96% rename from src/main/java/io/fabric8/maven/docker/assembly/DockerFileKeyword.java rename to src/main/java/io/fabric8/maven/docker/build/docker/DockerFileKeyword.java index 7a41a6812..2c029c8f4 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/DockerFileKeyword.java +++ b/src/main/java/io/fabric8/maven/docker/build/docker/DockerFileKeyword.java @@ -1,4 +1,4 @@ -package io.fabric8.maven.docker.assembly; +package io.fabric8.maven.docker.build.docker; /** * Fields for a dockerfile diff --git a/src/main/java/io/fabric8/maven/docker/assembly/DockerFileOption.java b/src/main/java/io/fabric8/maven/docker/build/docker/DockerFileOption.java similarity index 93% rename from src/main/java/io/fabric8/maven/docker/assembly/DockerFileOption.java rename to src/main/java/io/fabric8/maven/docker/build/docker/DockerFileOption.java index a1a6806f6..ec6debb70 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/DockerFileOption.java +++ b/src/main/java/io/fabric8/maven/docker/build/docker/DockerFileOption.java @@ -1,4 +1,4 @@ -package io.fabric8.maven.docker.assembly; +package io.fabric8.maven.docker.build.docker; /** * List of options for Docker keywords diff --git a/src/main/java/io/fabric8/maven/docker/build/docker/DockerRegistryService.java b/src/main/java/io/fabric8/maven/docker/build/docker/DockerRegistryService.java new file mode 100644 index 000000000..0c5edaf03 --- /dev/null +++ b/src/main/java/io/fabric8/maven/docker/build/docker/DockerRegistryService.java @@ -0,0 +1,133 @@ +package io.fabric8.maven.docker.build.docker; + +import java.io.IOException; + +import io.fabric8.maven.docker.access.AuthConfig; +import io.fabric8.maven.docker.access.DockerAccess; +import io.fabric8.maven.docker.access.DockerAccessException; +import io.fabric8.maven.docker.build.RegistryContext; +import io.fabric8.maven.docker.build.RegistryService; +import io.fabric8.maven.docker.config.BuildImageConfiguration; +import io.fabric8.maven.docker.config.ImageConfiguration; +import io.fabric8.maven.docker.config.ImagePullPolicy; +import io.fabric8.maven.docker.util.EnvUtil; +import io.fabric8.maven.docker.util.ImageName; +import io.fabric8.maven.docker.util.Logger; + +/** + * Allows to interact with registries, eg. to push/pull images. + */ +public class DockerRegistryService implements RegistryService { + + private final DockerAccess docker; + private final Logger log; + private final ImagePullCache imagePullCache; + + public DockerRegistryService(DockerAccess docker, Logger log, ImagePullCache.Backend backend) { + this.docker = docker; + this.log = log; + this.imagePullCache = new ImagePullCache(backend); + } + + /** + * Push a set of images to a registry + * + * @param imageConfig image to push but only if it has a build configuration + * @param retries how often to retry + * @param skipTag flag to skip pushing tagged images + * @throws DockerAccessException + */ + @Override + public void pushImage(ImageConfiguration imageConfig, + int retries, boolean skipTag, RegistryContext context) throws IOException { + BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); + String name = imageConfig.getName(); + if (buildConfig != null) { + String registry = EnvUtil.firstRegistryOf( + new ImageName(imageConfig.getName()).getRegistry(), + imageConfig.getRegistry(), + context.getPushRegistry()); + + + AuthConfig authConfig = context.lookupRegistryAuthConfig(true, new ImageName(name).getUser(), registry); + + long start = System.currentTimeMillis(); + docker.pushImage(name, authConfig, registry, retries); + log.info("Pushed %s in %s", name, EnvUtil.formatDurationTill(start)); + + if (!skipTag) { + for (String tag : imageConfig.getBuildConfiguration().getTags()) { + if (tag != null) { + docker.pushImage(new ImageName(name, tag).getFullName(), authConfig, registry, retries); + } + } + } + } + } + + + /** + * Check an image, and, if autoPull is set to true, fetch it. Otherwise if the image + * is not existent, throw an error + * + * @throws DockerAccessException + */ + public void pullImage(String image, ImagePullPolicy policy, RegistryContext registryContext) + throws DockerAccessException { + + // Already pulled, so we don't need to take care + if (imagePullCache.hasAlreadyPulled(image)) { + return; + } + + // Check if a pull is required + if (!imageRequiresPull(docker.hasImage(image), policy, image)) { + return; + } + + ImageName imageName = new ImageName(image); + long time = System.currentTimeMillis(); + String registry = EnvUtil.firstRegistryOf( + imageName.getRegistry(), + registryContext.getPullRegistry()); + + docker.pullImage(imageName.getFullName(), + registryContext.lookupRegistryAuthConfig(false, null, registry), + registry); + log.info("Pulled %s in %s", imageName.getFullName(), EnvUtil.formatDurationTill(time)); + imagePullCache.pulled(image); + + if (registry != null && !imageName.hasRegistry()) { + // If coming from a registry which was not contained in the original name, add a tag from the + // full name with the registry to the short name with no-registry. + docker.tag(imageName.getFullName(registry), image, false); + } + } + + + // ============================================================================================================ + + + private boolean imageRequiresPull(boolean hasImage, ImagePullPolicy pullPolicy, String imageName) { + + // The logic here is like this (see also #96): + // otherwise: don't pull + + if (pullPolicy == ImagePullPolicy.Never) { + if (!hasImage) { + throw new IllegalArgumentException( + String.format("No image '%s' found and pull policy 'Never' is set. Please chose another pull policy or pull the image yourself)", imageName)); + } + return false; + } + + // If the image is not available and mode is not ImagePullPolicy.Never --> pull + if (!hasImage) { + return true; + } + + // If pullPolicy == Always --> pull, otherwise not (we have it already) + return pullPolicy == ImagePullPolicy.Always; + } + +} diff --git a/src/main/java/io/fabric8/maven/docker/build/docker/ImagePullCache.java b/src/main/java/io/fabric8/maven/docker/build/docker/ImagePullCache.java new file mode 100644 index 000000000..7c3ad9625 --- /dev/null +++ b/src/main/java/io/fabric8/maven/docker/build/docker/ImagePullCache.java @@ -0,0 +1,81 @@ +package io.fabric8.maven.docker.build.docker; + +import com.google.gson.JsonObject; +import io.fabric8.maven.docker.util.JsonFactory; + +/** + * Simple interface for a ImagePullCache manager, to load and persist the cache. + */ +public class ImagePullCache { + + // Key for the previously used image cache + private static final String CONTEXT_KEY_PREVIOUSLY_PULLED = "CONTEXT_KEY_PREVIOUSLY_PULLED"; + + private Backend backend; + + public ImagePullCache(Backend backend) { + this.backend = backend; + } + + public boolean hasAlreadyPulled(String image) { + return load().has(image); + } + + public void pulled(String image) { + save(load().add(image)); + } + + // Store to use for the cached + public interface Backend { + String get(String key); + void put(String key, String value); + } + + // ====================================================================================== + + private ImagePullCacheStore load() { + + String pullCacheJson = backend.get(CONTEXT_KEY_PREVIOUSLY_PULLED); + + ImagePullCacheStore cache = new ImagePullCacheStore(pullCacheJson); + + if (pullCacheJson == null) { + save(cache); + } + return cache; + } + + private void save(ImagePullCacheStore cache) { + backend.put(CONTEXT_KEY_PREVIOUSLY_PULLED, cache.toString()); + } + + /** + * Simple serializable cache for holding image names + * + * @author roland + * @since 20/07/16 + */ + class ImagePullCacheStore { + + private JsonObject cache; + + + ImagePullCacheStore(String json) { + cache = json != null ? JsonFactory.newJsonObject(json) : new JsonObject(); + } + + public boolean has(String imageName) { + return cache.has(imageName); + } + + public ImagePullCacheStore add(String image) { + cache.addProperty(image, Boolean.TRUE); + return this; + } + + @Override + public String toString() { + return cache.toString(); + } + } +} diff --git a/src/main/java/io/fabric8/maven/docker/util/AuthConfigFactory.java b/src/main/java/io/fabric8/maven/docker/build/maven/AuthConfigFactory.java similarity index 88% rename from src/main/java/io/fabric8/maven/docker/util/AuthConfigFactory.java rename to src/main/java/io/fabric8/maven/docker/build/maven/AuthConfigFactory.java index 9fa4f1388..c07aa0e27 100644 --- a/src/main/java/io/fabric8/maven/docker/util/AuthConfigFactory.java +++ b/src/main/java/io/fabric8/maven/docker/build/maven/AuthConfigFactory.java @@ -1,4 +1,4 @@ -package io.fabric8.maven.docker.util; +package io.fabric8.maven.docker.build.maven; import com.google.gson.Gson; import com.google.gson.JsonObject; @@ -18,6 +18,9 @@ import io.fabric8.maven.docker.access.AuthConfig; import io.fabric8.maven.docker.access.ecr.EcrExtendedAuth; +import io.fabric8.maven.docker.util.CredentialHelperClient; +import io.fabric8.maven.docker.util.EnvUtil; +import io.fabric8.maven.docker.util.Logger; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.settings.Server; @@ -43,11 +46,15 @@ public class AuthConfigFactory { public static final String AUTH_EMAIL = "email"; public static final String AUTH_AUTHTOKEN = "authToken"; private static final String AUTH_USE_OPENSHIFT_AUTH = "useOpenShiftAuth"; + public static final String SKIP_EXTENDED_AUTH = "skipExtendedAuth"; static final String DOCKER_LOGIN_DEFAULT_REGISTRY = "https://index.docker.io/v1/"; private final PlexusContainer container; private final Gson gson; + private final Settings settings; + private final Map registryAuthConfig; + private final String defaultRegistry; private Logger log; private static final String[] DEFAULT_REGISTRIES = new String[]{ @@ -59,13 +66,13 @@ public class AuthConfigFactory { * * @param container the container used for do decryption of passwords */ - public AuthConfigFactory(PlexusContainer container) { + public AuthConfigFactory(PlexusContainer container, Settings settings, Map registryAuthConfig, String defaultRegistry, Logger log) { + this.settings = settings; this.container = container; - this.gson = new Gson(); - } - - public void setLog(Logger log) { + this.registryAuthConfig = registryAuthConfig; + this.defaultRegistry = defaultRegistry; this.log = log; + this.gson = new Gson(); } /** @@ -94,28 +101,24 @@ public void setLog(Logger log) { * and exchanged for ecr credentials. * * @param isPush if true this AuthConfig is created for a push, if false it's for a pull - * @param skipExtendedAuth if false, do not execute extended authentication methods - * @param authConfig String-String Map holding configuration info from the plugin's configuration. Can be null in - * which case the settings are consulted. - * @param settings the global Maven settings object * @param user user to check for - * @param registry registry to use, might be null in which case a default registry is checked, + * @param specificRegistry registry to use, might be null in which case a default registry is checked, * @return the authentication configuration or null if none could be found * * @throws MojoFailureException */ - public AuthConfig createAuthConfig(boolean isPush, boolean skipExtendedAuth, Map authConfig, Settings settings, String user, String registry) - throws MojoExecutionException { + public AuthConfig createAuthConfig(boolean isPush, String user, String specificRegistry) { - AuthConfig ret = createStandardAuthConfig(isPush, authConfig, settings, user, registry); + String registry = specificRegistry != null ? specificRegistry : defaultRegistry; + AuthConfig ret = createStandardAuthConfig(isPush, settings, user, registry); if (ret != null) { - if (registry == null || skipExtendedAuth) { + if (registry == null || Boolean.TRUE.equals(registryAuthConfig.get(SKIP_EXTENDED_AUTH))) { return ret; } try { return extendedAuthentication(ret, registry); } catch (IOException e) { - throw new MojoExecutionException(e.getMessage(), e); + throw new RuntimeException(e.getMessage(), e); } } @@ -141,7 +144,7 @@ public AuthConfig createAuthConfig(boolean isPush, boolean skipExtendedAuth, Map * @throws IOException * @throws MojoExecutionException */ - private AuthConfig extendedAuthentication(AuthConfig standardAuthConfig, String registry) throws IOException, MojoExecutionException { + private AuthConfig extendedAuthentication(AuthConfig standardAuthConfig, String registry) throws IOException { EcrExtendedAuth ecr = new EcrExtendedAuth(log, registry); if (ecr.isAwsRegistry()) { return ecr.extendedAuth(standardAuthConfig); @@ -171,8 +174,6 @@ private AuthConfig extendedAuthentication(AuthConfig standardAuthConfig, String * * * @param isPush if true this AuthConfig is created for a push, if false it's for a pull - * @param authConfigMap String-String Map holding configuration info from the plugin's configuration. Can be null in - * which case the settings are consulted. * @param settings the global Maven settings object * @param user user to check for * @param registry registry to use, might be null in which case a default registry is checked, @@ -180,8 +181,7 @@ private AuthConfig extendedAuthentication(AuthConfig standardAuthConfig, String * * @throws MojoFailureException */ - private AuthConfig createStandardAuthConfig(boolean isPush, Map authConfigMap, Settings settings, String user, String registry) - throws MojoExecutionException { + private AuthConfig createStandardAuthConfig(boolean isPush, Settings settings, String user, String registry) { AuthConfig ret; // Check first for specific configuration based on direction (pull or push), then for a default value @@ -194,14 +194,14 @@ private AuthConfig createStandardAuthConfig(boolean isPush, Map authConfigMap, S } // Check for openshift authentication either from the plugin config or from system props - ret = getAuthConfigFromOpenShiftConfig(lookupMode, authConfigMap); + ret = getAuthConfigFromOpenShiftConfig(lookupMode, registryAuthConfig); if (ret != null) { log.debug("AuthConfig: OpenShift credentials"); return ret; } // Get configuration from global plugin config - ret = getAuthConfigFromPluginConfiguration(lookupMode, authConfigMap); + ret = getAuthConfigFromPluginConfiguration(lookupMode, registryAuthConfig); if (ret != null) { log.debug("AuthConfig: credentials from plugin config"); return ret; @@ -224,13 +224,13 @@ private AuthConfig createStandardAuthConfig(boolean isPush, Map authConfigMap, S // =================================================================================================== - private AuthConfig getAuthConfigFromSystemProperties(LookupMode lookupMode) throws MojoExecutionException { + private AuthConfig getAuthConfigFromSystemProperties(LookupMode lookupMode) { Properties props = System.getProperties(); String userKey = lookupMode.asSysProperty(AUTH_USERNAME); String passwordKey = lookupMode.asSysProperty(AUTH_PASSWORD); if (props.containsKey(userKey)) { if (!props.containsKey(passwordKey)) { - throw new MojoExecutionException("No " + passwordKey + " provided for username " + props.getProperty(userKey)); + throw new IllegalArgumentException("No " + passwordKey + " provided for username " + props.getProperty(userKey)); } return new AuthConfig(props.getProperty(userKey), decrypt(props.getProperty(passwordKey)), @@ -241,7 +241,7 @@ private AuthConfig getAuthConfigFromSystemProperties(LookupMode lookupMode) thro } } - private AuthConfig getAuthConfigFromOpenShiftConfig(LookupMode lookupMode, Map authConfigMap) throws MojoExecutionException { + private AuthConfig getAuthConfigFromOpenShiftConfig(LookupMode lookupMode, Map authConfigMap) { Properties props = System.getProperties(); String useOpenAuthModeProp = lookupMode.asSysProperty(AUTH_USE_OPENSHIFT_AUTH); // Check for system property @@ -264,12 +264,12 @@ private AuthConfig getAuthConfigFromOpenShiftConfig(LookupMode lookupMode, Map a } } - private AuthConfig getAuthConfigFromPluginConfiguration(LookupMode lookupMode, Map authConfig) throws MojoExecutionException { + private AuthConfig getAuthConfigFromPluginConfiguration(LookupMode lookupMode, Map authConfig) { Map mapToCheck = getAuthConfigMapToCheck(lookupMode,authConfig); if (mapToCheck != null && mapToCheck.containsKey(AUTH_USERNAME)) { if (!mapToCheck.containsKey(AUTH_PASSWORD)) { - throw new MojoExecutionException("No 'password' given while using in configuration for mode " + lookupMode); + throw new IllegalArgumentException("No 'password' given while using in configuration for mode " + lookupMode); } Map cloneConfig = new HashMap<>(mapToCheck); cloneConfig.put(AUTH_PASSWORD, decrypt(cloneConfig.get(AUTH_PASSWORD))); @@ -279,7 +279,7 @@ private AuthConfig getAuthConfigFromPluginConfiguration(LookupMode lookupMode, M } } - private AuthConfig getAuthConfigFromSettings(Settings settings, String user, String registry) throws MojoExecutionException { + private AuthConfig getAuthConfigFromSettings(Settings settings, String user, String registry) { Server defaultServer = null; Server found; for (Server server : settings.getServers()) { @@ -298,7 +298,7 @@ private AuthConfig getAuthConfigFromSettings(Settings settings, String user, Str return defaultServer != null ? createAuthConfigFromServer(defaultServer) : null; } - private AuthConfig getAuthConfigFromDockerConfig(String registry) throws MojoExecutionException { + private AuthConfig getAuthConfigFromDockerConfig(String registry) { JsonObject dockerConfig = readDockerConfig(); if (dockerConfig == null) { return null; @@ -334,7 +334,7 @@ private AuthConfig extractAuthConfigFromAuths(String registryToLookup, JsonObjec return new AuthConfig(auth,email); } - private AuthConfig extractAuthConfigFromCredentialsHelper(String registryToLookup, String credConfig) throws MojoExecutionException { + private AuthConfig extractAuthConfigFromCredentialsHelper(String registryToLookup, String credConfig) { CredentialHelperClient credentialHelper = new CredentialHelperClient(log, credConfig); log.debug("AuthConfig: credentials from credential helper/store %s version %s", credentialHelper.getName(), @@ -424,19 +424,19 @@ private AuthConfig parseUser(String userName, Map user) { token, null, null); } - private AuthConfig validateMandatoryOpenShiftLogin(AuthConfig openShiftAuthConfig, String useOpenAuthModeProp) throws MojoExecutionException { + private AuthConfig validateMandatoryOpenShiftLogin(AuthConfig openShiftAuthConfig, String useOpenAuthModeProp) { if (openShiftAuthConfig != null) { return openShiftAuthConfig; } // No login found String kubeConfigEnv = System.getenv("KUBECONFIG"); - throw new MojoExecutionException( + throw new IllegalArgumentException( String.format("System property %s set, but not active user and/or token found in %s. " + "Please use 'oc login' for connecting to OpenShift.", useOpenAuthModeProp, kubeConfigEnv != null ? kubeConfigEnv : "~/.kube/config")); } - + private JsonObject readDockerConfig() { String dockerConfig = System.getenv("DOCKER_CONFIG"); @@ -492,20 +492,20 @@ private Server checkForServer(Server server, String id, String registry, String return null; } - private String decrypt(String password) throws MojoExecutionException { + private String decrypt(String password) { try { // Done by reflection since I have classloader issues otherwise Object secDispatcher = container.lookup(SecDispatcher.ROLE, "maven"); Method method = secDispatcher.getClass().getMethod("decrypt",String.class); return (String) method.invoke(secDispatcher,password); } catch (ComponentLookupException e) { - throw new MojoExecutionException("Error looking security dispatcher",e); + throw new IllegalStateException("Error looking security dispatcher",e); } catch (ReflectiveOperationException e) { - throw new MojoExecutionException("Cannot decrypt password: " + e.getCause(),e); + throw new IllegalStateException("Cannot decrypt password: " + e.getCause(),e); } } - private AuthConfig createAuthConfigFromServer(Server server) throws MojoExecutionException { + private AuthConfig createAuthConfigFromServer(Server server) { return new AuthConfig( server.getUsername(), decrypt(server.getPassword()), diff --git a/src/main/java/io/fabric8/maven/docker/service/ArchiveService.java b/src/main/java/io/fabric8/maven/docker/build/maven/MavenArchiveService.java similarity index 68% rename from src/main/java/io/fabric8/maven/docker/service/ArchiveService.java rename to src/main/java/io/fabric8/maven/docker/build/maven/MavenArchiveService.java index 48ffa8514..fef981a14 100644 --- a/src/main/java/io/fabric8/maven/docker/service/ArchiveService.java +++ b/src/main/java/io/fabric8/maven/docker/build/maven/MavenArchiveService.java @@ -1,5 +1,5 @@ -package io.fabric8.maven.docker.service;/* - * +package io.fabric8.maven.docker.build.maven;/* + * * Copyright 2015 Roland Huss * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,33 +15,32 @@ * limitations under the License. */ -import io.fabric8.maven.docker.assembly.ArchiverCustomizer; -import io.fabric8.maven.docker.assembly.AssemblyFiles; -import io.fabric8.maven.docker.assembly.DockerAssemblyManager; +import java.io.File; +import java.io.IOException; +import java.util.List; + +import io.fabric8.maven.docker.build.maven.assembly.ArchiverCustomizer; +import io.fabric8.maven.docker.build.maven.assembly.AssemblyFiles; +import io.fabric8.maven.docker.build.maven.assembly.DockerAssemblyManager; import io.fabric8.maven.docker.config.BuildImageConfiguration; import io.fabric8.maven.docker.config.ImageConfiguration; import io.fabric8.maven.docker.util.Logger; -import io.fabric8.maven.docker.util.MojoParameters; -import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.assembly.InvalidAssemblerConfigurationException; import org.apache.maven.plugins.assembly.archive.ArchiveCreationException; import org.apache.maven.plugins.assembly.format.AssemblyFormattingException; -import java.io.File; -import java.util.List; - /** * @author roland * @since 30/11/15 */ -public class ArchiveService { +public class MavenArchiveService { private final Logger log; private DockerAssemblyManager dockerAssemblyManager; - public ArchiveService(DockerAssemblyManager dockerAssemblyManager,Logger log) { + public MavenArchiveService(DockerAssemblyManager dockerAssemblyManager, Logger log) { this.log = log; this.dockerAssemblyManager = dockerAssemblyManager; } @@ -53,10 +52,10 @@ public ArchiveService(DockerAssemblyManager dockerAssemblyManager,Logger log) { * @param imageConfig the image configuration * @param params mojo params for the project * @return file for holding the sources - * @throws MojoExecutionException if during creation of the tar an error occurs. + * @throws IOException if during creation of the tar an error occurs. */ - public File createDockerBuildArchive(ImageConfiguration imageConfig, MojoParameters params) - throws MojoExecutionException { + public File createDockerBuildArchive(ImageConfiguration imageConfig, MavenBuildContext params) + throws IOException { return createDockerBuildArchive(imageConfig, params, null); } @@ -65,14 +64,14 @@ public File createDockerBuildArchive(ImageConfiguration imageConfig, MojoParamet * uploading to a Docker daemon for creating the image * * @param imageConfig the image configuration - * @param params mojo params for the project + * @param context mojo params for the project * @param customizer final customizer to be applied to the tar before being generated * @return file for holding the sources - * @throws MojoExecutionException if during creation of the tar an error occurs. + * @throws IOException if during creation of the tar an error occurs. */ - public File createDockerBuildArchive(ImageConfiguration imageConfig, MojoParameters params, ArchiverCustomizer customizer) - throws MojoExecutionException { - File ret = createArchive(imageConfig.getName(), imageConfig.getBuildConfiguration(), params, log, customizer); + public File createDockerBuildArchive(ImageConfiguration imageConfig, MavenBuildContext context, ArchiverCustomizer customizer) + throws IOException { + File ret = createArchive(imageConfig.getName(), imageConfig.getBuildConfiguration(), context, log, customizer); log.info("%s: Created docker source tar %s",imageConfig.getDescription(), ret); return ret; } @@ -84,18 +83,18 @@ public File createDockerBuildArchive(ImageConfiguration imageConfig, MojoParamet * * @param imageConfig image config for which to get files. The build- and assembly configuration in this image * config must not be null. - * @param mojoParameters needed for tracking the assembly + * @param context needed for tracking the assembly * @return mapping of assembly files - * @throws MojoExecutionException + * @throws IOException */ - public AssemblyFiles getAssemblyFiles(ImageConfiguration imageConfig, MojoParameters mojoParameters) - throws MojoExecutionException { + public AssemblyFiles getAssemblyFiles(ImageConfiguration imageConfig, MavenBuildContext context) + throws IOException { String name = imageConfig.getName(); try { - return dockerAssemblyManager.getAssemblyFiles(name, imageConfig.getBuildConfiguration(), mojoParameters, log); + return dockerAssemblyManager.getAssemblyFiles(name, imageConfig.getBuildConfiguration(), context, log); } catch (InvalidAssemblerConfigurationException | ArchiveCreationException | AssemblyFormattingException e) { - throw new MojoExecutionException("Cannot extract assembly files for image " + name + ": " + e, e); + throw new IOException("Cannot extract assembly files for image " + name + ": " + e, e); } } @@ -107,19 +106,19 @@ public AssemblyFiles getAssemblyFiles(ImageConfiguration imageConfig, MojoParame * @return created archive */ public File createChangedFilesArchive(List entries, File assemblyDir, - String imageName, MojoParameters mojoParameters) throws MojoExecutionException { + String imageName, MavenBuildContext mojoParameters) throws IOException { return dockerAssemblyManager.createChangedFilesArchive(entries, assemblyDir, imageName, mojoParameters); } // ============================================= - File createArchive(String imageName, BuildImageConfiguration buildConfig, MojoParameters params, Logger log) - throws MojoExecutionException { - return createArchive(imageName, buildConfig, params, log, null); + public File createArchive(String imageName, BuildImageConfiguration buildConfig, MavenBuildContext ctx, Logger log) + throws IOException { + return createArchive(imageName, buildConfig, ctx, log, null); } - File createArchive(String imageName, BuildImageConfiguration buildConfig, MojoParameters params, Logger log, ArchiverCustomizer customizer) - throws MojoExecutionException { - return dockerAssemblyManager.createDockerTarArchive(imageName, params, buildConfig, log, customizer); + File createArchive(String imageName, BuildImageConfiguration buildConfig, MavenBuildContext ctx, Logger log, ArchiverCustomizer customizer) + throws IOException { + return dockerAssemblyManager.createDockerTarArchive(imageName, ctx, buildConfig, customizer, log); } } diff --git a/src/main/java/io/fabric8/maven/docker/build/maven/MavenBuildContext.java b/src/main/java/io/fabric8/maven/docker/build/maven/MavenBuildContext.java new file mode 100644 index 000000000..5839d31ac --- /dev/null +++ b/src/main/java/io/fabric8/maven/docker/build/maven/MavenBuildContext.java @@ -0,0 +1,189 @@ +package io.fabric8.maven.docker.build.maven; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.List; +import java.util.Properties; +import java.util.function.Function; + +import io.fabric8.maven.docker.build.BuildContext; +import io.fabric8.maven.docker.build.RegistryContext; +import io.fabric8.maven.docker.config.BuildImageConfiguration; +import io.fabric8.maven.docker.util.DockerFileUtil; +import io.fabric8.maven.docker.util.Logger; +import org.apache.maven.archiver.MavenArchiveConfiguration; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.project.MavenProject; +import org.apache.maven.settings.Settings; +import org.apache.maven.shared.filtering.MavenFileFilter; +import org.apache.maven.shared.filtering.MavenReaderFilter; +import org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator; + +/** + * @author roland + * @since 16.10.18 + */ +public class MavenBuildContext implements BuildContext, Serializable { + + private String sourceDirectory; + private String outputDirectory; + private MavenProject project; + private MavenSession session; + private MavenFileFilter mavenFileFilter; + private MavenReaderFilter mavenReaderFilter; + private Settings settings; + private List reactorProjects; + private MavenArchiveConfiguration archiveConfiguration; + private MavenArchiveService archiveService; + private RegistryContext registryContext; + + public MavenBuildContext() { + } + + + public String getSourceDirectory() { + return sourceDirectory; + } + + public String getOutputDirectory() { + return outputDirectory; + } + + + public File getBasedir() { + return project.getBasedir(); + } + + @Override + public Properties getProperties() { + return project.getProperties(); + } + + @Override + public Function createInterpolator(String filter) { + FixedStringSearchInterpolator interpolator = + DockerFileUtil.createInterpolator(this, filter); + return interpolator::interpolate; + } + + @Override + public File createImageContentArchive(String imageName, BuildImageConfiguration buildConfig, Logger log) throws IOException { + return archiveService.createArchive(imageName, buildConfig, this, log); + } + + @Override + public RegistryContext getRegistryContext() { + return registryContext; + } + + // ======================================================================================= + // Maven specific method not available via interface + + public MavenProject getProject() { + return project; + } + + public MavenSession getSession() { + return session; + } + + public MavenFileFilter getMavenFileFilter() { + return mavenFileFilter; + } + + public MavenReaderFilter getMavenReaderFilter() { + return mavenReaderFilter; + } + + public Settings getSettings() { + return settings; + } + + public List getReactorProjects() { + return reactorProjects; + } + + public MavenArchiveConfiguration getArchiveConfiguration() { + return archiveConfiguration; + } + + // ======================================================================================= + public static class Builder { + + private MavenBuildContext context; + + public Builder() { + this.context = new MavenBuildContext(); + } + + public Builder(MavenBuildContext context) { + this.context = context; + } + + public Builder sourceDirectory(String sourceDirectory) { + context.sourceDirectory = sourceDirectory; + return this; + } + + public Builder outputDirectory(String outputDirectory) { + context.outputDirectory = outputDirectory; + return this; + } + + public Builder registryContext(RegistryContext registryContext) { + context.registryContext = registryContext; + return this; + } + + // =============================================================================== + // Maven specific calls + + public Builder project(MavenProject project) { + context.project = project; + return this; + } + + public Builder session(MavenSession session) { + context.session = session; + return this; + } + + public Builder settings(Settings settings) { + context.settings = settings; + return this; + } + + public Builder mavenReaderFilter(MavenReaderFilter mavenReaderFilter) { + context.mavenReaderFilter = mavenReaderFilter; + return this; + } + + public Builder mavenFileFilter(MavenFileFilter mavenFileFilter) { + context.mavenFileFilter = mavenFileFilter; + return this; + } + + public Builder reactorProjects(List reactorProjects) { + context.reactorProjects = reactorProjects; + return this; + } + + public Builder archiveConfiguration(MavenArchiveConfiguration archiveConfiguration) { + context.archiveConfiguration = archiveConfiguration; + return this; + } + + public Builder archiveService(MavenArchiveService archiveService) { + context.archiveService = archiveService; + return this; + } + + // ================================================================================ + public MavenBuildContext build() { + return context; + } + + + } +} diff --git a/src/main/java/io/fabric8/maven/docker/build/maven/MavenCacheBackend.java b/src/main/java/io/fabric8/maven/docker/build/maven/MavenCacheBackend.java new file mode 100644 index 000000000..04f8cc3e7 --- /dev/null +++ b/src/main/java/io/fabric8/maven/docker/build/maven/MavenCacheBackend.java @@ -0,0 +1,31 @@ +package io.fabric8.maven.docker.build.maven; + +import java.util.Properties; + +import io.fabric8.maven.docker.build.docker.ImagePullCache; +import org.apache.maven.execution.MavenSession; + +/** + * @author roland + * @since 17.10.18 + */ +public class MavenCacheBackend implements ImagePullCache.Backend { + + private MavenSession session; + + public MavenCacheBackend(MavenSession session) { + this.session = session; + } + + @Override + public String get(String key) { + Properties userProperties = session.getUserProperties(); + return userProperties.getProperty(key); + } + + @Override + public void put(String key, String value) { + Properties userProperties = session.getUserProperties(); + userProperties.setProperty(key, value); + } +} diff --git a/src/main/java/io/fabric8/maven/docker/build/maven/MavenRegistryContext.java b/src/main/java/io/fabric8/maven/docker/build/maven/MavenRegistryContext.java new file mode 100644 index 000000000..76c9ab7b2 --- /dev/null +++ b/src/main/java/io/fabric8/maven/docker/build/maven/MavenRegistryContext.java @@ -0,0 +1,70 @@ +package io.fabric8.maven.docker.build.maven; + +import io.fabric8.maven.docker.access.AuthConfig; +import io.fabric8.maven.docker.build.RegistryContext; +import io.fabric8.maven.docker.config.ImagePullPolicy; + +/** + * @author roland + * @since 17.10.18 + */ +public class MavenRegistryContext implements RegistryContext { + + private ImagePullPolicy defaultImagePullPolicy; + private AuthConfigFactory authConfigFactory; + private String pushRegistry; + private String pullRegistry; + + @Override + public ImagePullPolicy getDefaultImagePullPolicy() { + return defaultImagePullPolicy; + } + + @Override + public AuthConfig lookupRegistryAuthConfig(boolean isPush, String user, String registry) { + return authConfigFactory.createAuthConfig(isPush, user, registry); + } + + @Override + public String getPushRegistry() { + return pushRegistry; + } + + @Override + public String getPullRegistry() { + return pullRegistry; + } + + // =============================================================================================== + + public static class Builder { + + private MavenRegistryContext context = new MavenRegistryContext(); + + public Builder defaultImagePullPolicy(ImagePullPolicy defaultImagePullPolicy) { + context.defaultImagePullPolicy = defaultImagePullPolicy; + return this; + } + + public Builder pushRegistry(String pushRegistry) { + context.pushRegistry = pushRegistry; + return this; + } + + public Builder pullRegistry(String pullRegistry) { + context.pullRegistry = pullRegistry; + return this; + } + + public Builder authConfigFactory(AuthConfigFactory authConfigFactory) { + context.authConfigFactory = authConfigFactory; + return this; + } + + // ================================================================================ + public MavenRegistryContext build() { + return context; + } + + } +} diff --git a/src/main/java/io/fabric8/maven/docker/assembly/AllFilesExecCustomizer.java b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/AllFilesExecCustomizer.java similarity index 98% rename from src/main/java/io/fabric8/maven/docker/assembly/AllFilesExecCustomizer.java rename to src/main/java/io/fabric8/maven/docker/build/maven/assembly/AllFilesExecCustomizer.java index 80df6319d..6a40bc1c1 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/AllFilesExecCustomizer.java +++ b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/AllFilesExecCustomizer.java @@ -1,4 +1,4 @@ -package io.fabric8.maven.docker.assembly; +package io.fabric8.maven.docker.build.maven.assembly; /* * * Copyright 2016 Roland Huss diff --git a/src/main/java/io/fabric8/maven/docker/assembly/ArchiverCustomizer.java b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/ArchiverCustomizer.java similarity index 94% rename from src/main/java/io/fabric8/maven/docker/assembly/ArchiverCustomizer.java rename to src/main/java/io/fabric8/maven/docker/build/maven/assembly/ArchiverCustomizer.java index 316d71828..3ed88706f 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/ArchiverCustomizer.java +++ b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/ArchiverCustomizer.java @@ -13,7 +13,7 @@ * implied. See the License for the specific language governing * permissions and limitations under the License. */ -package io.fabric8.maven.docker.assembly; +package io.fabric8.maven.docker.build.maven.assembly; import java.io.IOException; diff --git a/src/main/java/io/fabric8/maven/docker/assembly/AssemblyFiles.java b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/AssemblyFiles.java similarity index 98% rename from src/main/java/io/fabric8/maven/docker/assembly/AssemblyFiles.java rename to src/main/java/io/fabric8/maven/docker/build/maven/assembly/AssemblyFiles.java index f756fc5dc..9906288cd 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/AssemblyFiles.java +++ b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/AssemblyFiles.java @@ -1,4 +1,4 @@ -package io.fabric8.maven.docker.assembly;/* +package io.fabric8.maven.docker.build.maven.assembly;/* * * Copyright 2014 Roland Huss * diff --git a/src/main/java/io/fabric8/maven/docker/assembly/BuildDirs.java b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/BuildDirs.java similarity index 81% rename from src/main/java/io/fabric8/maven/docker/assembly/BuildDirs.java rename to src/main/java/io/fabric8/maven/docker/build/maven/assembly/BuildDirs.java index f81d3a5c4..a8693ce2b 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/BuildDirs.java +++ b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/BuildDirs.java @@ -1,5 +1,5 @@ -package io.fabric8.maven.docker.assembly;/* - * +package io.fabric8.maven.docker.build.maven.assembly;/* + * * Copyright 2014 Roland Huss * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,7 @@ import java.io.File; -import io.fabric8.maven.docker.util.MojoParameters; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import io.fabric8.maven.docker.util.EnvUtil; /** @@ -30,16 +30,16 @@ class BuildDirs { private final String buildTopDir; - private final MojoParameters params; + private final MavenBuildContext context; /** * Constructor building up the the output directories * * @param imageName image name for the image to build - * @param params mojo params holding base and global outptput dir + * @param context mojo params holding base and global outptput dir */ - BuildDirs(String imageName, MojoParameters params) { - this.params = params; + BuildDirs(String imageName, MavenBuildContext context) { + this.context = context; // Replace tag separator with a slash to avoid problems // with OSs which gets confused by colons. this.buildTopDir = imageName != null ? imageName.replace(':', '/') : null; @@ -69,6 +69,6 @@ void createDirs() { } private File getDir(String dir) { - return EnvUtil.prepareAbsoluteOutputDirPath(params, buildTopDir, dir); + return EnvUtil.prepareAbsoluteOutputDirPath(context, buildTopDir, dir); } } diff --git a/src/main/java/io/fabric8/maven/docker/assembly/DockerAssemblyConfigurationSource.java b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyConfigurationSource.java similarity index 91% rename from src/main/java/io/fabric8/maven/docker/assembly/DockerAssemblyConfigurationSource.java rename to src/main/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyConfigurationSource.java index f5accd095..4c7a7e289 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/DockerAssemblyConfigurationSource.java +++ b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyConfigurationSource.java @@ -1,4 +1,4 @@ -package io.fabric8.maven.docker.assembly; +package io.fabric8.maven.docker.build.maven.assembly; import java.io.File; import java.util.Collections; @@ -7,8 +7,8 @@ import javax.annotation.Nonnull; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import io.fabric8.maven.docker.config.AssemblyConfiguration; -import io.fabric8.maven.docker.util.MojoParameters; import io.fabric8.maven.docker.util.EnvUtil; import org.apache.maven.archiver.MavenArchiveConfiguration; import org.apache.maven.artifact.repository.ArtifactRepository; @@ -30,7 +30,7 @@ public class DockerAssemblyConfigurationSource implements AssemblerConfigurationSource { private final AssemblyConfiguration assemblyConfig; - private final MojoParameters params; + private final MavenBuildContext context; private final BuildDirs buildDirs; // Required by configuration source and duplicated from AbstractAssemblyMojo (which is unfortunately @@ -40,8 +40,8 @@ public class DockerAssemblyConfigurationSource implements AssemblerConfiguration private FixedStringSearchInterpolator rootInterpolator; private FixedStringSearchInterpolator mainProjectInterpolator; - public DockerAssemblyConfigurationSource(MojoParameters params, BuildDirs buildDirs, AssemblyConfiguration assemblyConfig) { - this.params = params; + public DockerAssemblyConfigurationSource(MavenBuildContext context, BuildDirs buildDirs, AssemblyConfiguration assemblyConfig) { + this.context = context; this.assemblyConfig = assemblyConfig; this.buildDirs = buildDirs; } @@ -52,7 +52,7 @@ public String[] getDescriptors() { String descriptor = assemblyConfig.getDescriptor(); if (descriptor != null) { - return new String[] {EnvUtil.prepareAbsoluteSourceDirPath(params, descriptor).getAbsolutePath() }; + return new String[] {EnvUtil.prepareAbsoluteSourceDirPath(context, descriptor).getAbsolutePath() }; } } return new String[0]; @@ -95,39 +95,39 @@ public String getFinalName() { @Override public ArtifactRepository getLocalRepository() { - return params.getSession().getLocalRepository(); + return context.getSession().getLocalRepository(); } - + public MavenFileFilter getMavenFileFilter() { - return params.getMavenFileFilter(); + return context.getMavenFileFilter(); } // Maybe use injection @Override public List getReactorProjects() { - return params.getReactorProjects(); + return context.getReactorProjects(); } // Maybe use injection @Override public List getRemoteRepositories() { - return params.getProject().getRemoteArtifactRepositories(); + return context.getProject().getRemoteArtifactRepositories(); } @Override public MavenSession getMavenSession() { - return params.getSession(); + return context.getSession(); } @Override public MavenArchiveConfiguration getJarArchiveConfiguration() { - return params.getArchiveConfiguration(); + return context.getArchiveConfiguration(); } // X @Override public String getEncoding() { - return params.getProject().getProperties().getProperty("project.build.sourceEncoding"); + return context.getProject().getProperties().getProperty("project.build.sourceEncoding"); } // X @@ -180,13 +180,13 @@ public FixedStringSearchInterpolator getMainProjectInterpolator() // X @Override public MavenProject getProject() { - return params.getProject(); + return context.getProject(); } // X @Override public File getBasedir() { - return params.getProject().getBasedir(); + return context.getProject().getBasedir(); } // X @@ -256,7 +256,7 @@ public String getArchiverConfig() { @Override public MavenReaderFilter getMavenReaderFilter() { - return params.getMavenFilterReader(); + return context.getMavenReaderFilter(); } @Override diff --git a/src/main/java/io/fabric8/maven/docker/assembly/DockerAssemblyManager.java b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyManager.java similarity index 79% rename from src/main/java/io/fabric8/maven/docker/assembly/DockerAssemblyManager.java rename to src/main/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyManager.java index 8760c2ced..c55060077 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/DockerAssemblyManager.java +++ b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyManager.java @@ -1,4 +1,4 @@ -package io.fabric8.maven.docker.assembly; +package io.fabric8.maven.docker.build.maven.assembly; import java.io.File; import java.io.FileWriter; @@ -7,7 +7,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.Function; +import io.fabric8.maven.docker.build.docker.DockerFileBuilder; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import io.fabric8.maven.docker.config.ArchiveCompression; import io.fabric8.maven.docker.config.Arguments; import io.fabric8.maven.docker.config.AssemblyConfiguration; @@ -16,7 +19,6 @@ import io.fabric8.maven.docker.util.DockerFileUtil; import io.fabric8.maven.docker.util.EnvUtil; import io.fabric8.maven.docker.util.Logger; -import io.fabric8.maven.docker.util.MojoParameters; import org.apache.commons.io.IOUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Build; @@ -54,7 +56,6 @@ public class DockerAssemblyManager { public static final String DEFAULT_DATA_BASE_IMAGE = "busybox:latest"; - public static final String SCRATCH_IMAGE = "scratch"; // Assembly name used also as build directory within outputBuildDir public static final String DOCKER_IGNORE = ".maven-dockerignore"; @@ -79,15 +80,15 @@ public class DockerAssemblyManager { * creating the image. * * @param imageName Name of the image to create (used for creating build directories) - * @param params Mojos parameters (used for finding the directories) + * @param context Mojos parameters (used for finding the directories) * @param buildConfig configuration for how to build the image * @param log Logger used to display warning if permissions are to be normalized * @return file holding the path to the created assembly tar file * @throws MojoExecutionException */ - public File createDockerTarArchive(String imageName, MojoParameters params, BuildImageConfiguration buildConfig, Logger log) - throws MojoExecutionException { - return createDockerTarArchive(imageName, params, buildConfig, log, null); + public File createDockerTarArchive(String imageName, MavenBuildContext context, BuildImageConfiguration buildConfig, Logger log) + throws IOException { + return createDockerTarArchive(imageName, context, buildConfig, null, log); } /** @@ -95,58 +96,55 @@ public File createDockerTarArchive(String imageName, MojoParameters params, Buil * creating the image. * * @param imageName Name of the image to create (used for creating build directories) - * @param params Mojos parameters (used for finding the directories) + * @param context Mojos parameters (used for finding the directories) * @param buildConfig configuration for how to build the image - * @param log Logger used to display warning if permissions are to be normalized * @param finalCustomizer finalCustomizer to be applied to the tar archive * @return file holding the path to the created assembly tar file * @throws MojoExecutionException */ - public File createDockerTarArchive(String imageName, final MojoParameters params, final BuildImageConfiguration buildConfig, Logger log, ArchiverCustomizer finalCustomizer) - throws MojoExecutionException { + public File createDockerTarArchive(String imageName, final MavenBuildContext context, final BuildImageConfiguration buildConfig, ArchiverCustomizer finalCustomizer, Logger log) + throws IOException { - final BuildDirs buildDirs = createBuildDirs(imageName, params); + final BuildDirs buildDirs = createBuildDirs(imageName, context); final AssemblyConfiguration assemblyConfig = buildConfig.getAssemblyConfiguration(); final List archiveCustomizers = new ArrayList<>(); // Build up assembly. In dockerfile mode this must be added explicitly in the Dockerfile with an ADD if (hasAssemblyConfiguration(assemblyConfig)) { - createAssemblyArchive(assemblyConfig, params, buildDirs); + createAssemblyArchive(assemblyConfig, context, buildDirs); } try { if (buildConfig.isDockerFileMode()) { // Use specified docker directory which must include a Dockerfile. - final File dockerFile = buildConfig.getAbsoluteDockerFilePath(params); + final File dockerFile = + EnvUtil.prepareAbsoluteSourceDirPath(context, buildConfig.getDockerFile().getPath()); if (!dockerFile.exists()) { - throw new MojoExecutionException("Configured Dockerfile \"" + + throw new IOException("Configured Dockerfile \"" + buildConfig.getDockerFile() + "\" (resolved to \"" + dockerFile + "\") doesn't exist"); } - FixedStringSearchInterpolator interpolator = DockerFileUtil.createInterpolator(params, buildConfig.getFilter()); - verifyGivenDockerfile(dockerFile, buildConfig, interpolator, log); + FixedStringSearchInterpolator interpolator = DockerFileUtil.createInterpolator(context, buildConfig.getFilter()); + verifyGivenDockerfile(dockerFile, buildConfig, interpolator::interpolate, log); interpolateDockerfile(dockerFile, buildDirs, interpolator); // User dedicated Dockerfile from extra directory - archiveCustomizers.add(new ArchiverCustomizer() { - @Override - public TarArchiver customize(TarArchiver archiver) throws IOException { - DefaultFileSet fileSet = DefaultFileSet.fileSet(dockerFile.getParentFile()); - addDockerIncludesExcludesIfPresent(fileSet, params); - // Exclude non-interpolated dockerfile from source tree - // Interpolated Dockerfile is already added as it was created into the output directory when - // using dir dir mode - excludeDockerfile(fileSet, dockerFile); - - // If the content is added as archive, then we need to add the Dockerfile from the builddir - // directly to docker.tar (as the output builddir is not picked up in archive mode) - if (isArchive(assemblyConfig)) { - String name = dockerFile.getName(); - archiver.addFile(new File(buildDirs.getOutputDirectory(), name), name); - } - - archiver.addFileSet(fileSet); - return archiver; + archiveCustomizers.add(archiver -> { + DefaultFileSet fileSet = DefaultFileSet.fileSet(dockerFile.getParentFile()); + addDockerIncludesExcludesIfPresent(fileSet, context); + // Exclude non-interpolated dockerfile from source tree + // Interpolated Dockerfile is already added as it was created into the output directory when + // using dir dir mode + excludeDockerfile(fileSet, dockerFile); + + // If the content is added as archive, then we need to add the Dockerfile from the builddir + // directly to docker.tar (as the output builddir is not picked up in archive mode) + if (isArchive(assemblyConfig)) { + String name = dockerFile.getName(); + archiver.addFile(new File(buildDirs.getOutputDirectory(), name), name); } + + archiver.addFileSet(fileSet); + return archiver; }); } else { // Create custom docker file in output dir @@ -154,12 +152,9 @@ public TarArchiver customize(TarArchiver archiver) throws IOException { builder.write(buildDirs.getOutputDirectory()); // Add own Dockerfile final File dockerFile = new File(buildDirs.getOutputDirectory(), DOCKERFILE_NAME); - archiveCustomizers.add(new ArchiverCustomizer() { - @Override - public TarArchiver customize(TarArchiver archiver) throws IOException { - archiver.addFile(dockerFile, DOCKERFILE_NAME); - return archiver; - } + archiveCustomizers.add(archiver -> { + archiver.addFile(dockerFile, DOCKERFILE_NAME); + return archiver; }); } @@ -179,7 +174,7 @@ public TarArchiver customize(TarArchiver archiver) throws IOException { return createBuildTarBall(buildDirs, archiveCustomizers, assemblyConfig, buildConfig.getCompression()); } catch (IOException e) { - throw new MojoExecutionException(String.format("Cannot create %s in %s", DOCKERFILE_NAME, buildDirs.getOutputDirectory()), e); + throw new IOException(String.format("Cannot create %s in %s", DOCKERFILE_NAME, buildDirs.getOutputDirectory()), e); } } @@ -202,7 +197,7 @@ private void interpolateDockerfile(File dockerFile, BuildDirs params, FixedStrin } // visible for testing - void verifyGivenDockerfile(File dockerFile, BuildImageConfiguration buildConfig, FixedStringSearchInterpolator interpolator, Logger log) throws IOException { + void verifyGivenDockerfile(File dockerFile, BuildImageConfiguration buildConfig, Function interpolator, Logger log) throws IOException { AssemblyConfiguration assemblyConfig = buildConfig.getAssemblyConfiguration(); if (assemblyConfig == null) { return; @@ -237,15 +232,15 @@ void verifyGivenDockerfile(File dockerFile, BuildImageConfiguration buildConfig, * Extract all files with a tracking archiver. These can be used to track changes in the filesystem and triggering * a rebuild of the image if needed ('docker:watch') */ - public AssemblyFiles getAssemblyFiles(String name, BuildImageConfiguration buildConfig, MojoParameters mojoParams, Logger log) - throws InvalidAssemblerConfigurationException, ArchiveCreationException, AssemblyFormattingException, MojoExecutionException { + public AssemblyFiles getAssemblyFiles(String name, BuildImageConfiguration buildConfig, MavenBuildContext context, Logger log) + throws InvalidAssemblerConfigurationException, ArchiveCreationException, AssemblyFormattingException, IOException { - BuildDirs buildDirs = createBuildDirs(name, mojoParams); + BuildDirs buildDirs = createBuildDirs(name, context); AssemblyConfiguration assemblyConfig = buildConfig.getAssemblyConfiguration(); String assemblyName = assemblyConfig.getName(); DockerAssemblyConfigurationSource source = - new DockerAssemblyConfigurationSource(mojoParams, buildDirs, assemblyConfig); + new DockerAssemblyConfigurationSource(context, buildDirs, assemblyConfig); Assembly assembly = getAssemblyConfig(assemblyConfig, source); @@ -254,12 +249,12 @@ public AssemblyFiles getAssemblyFiles(String name, BuildImageConfiguration build ta.init(log, assemblyName); assembly.setId("tracker"); assemblyArchiver.createArchive(assembly, assemblyName, "track", source, false, null); - return ta.getAssemblyFiles(mojoParams.getSession()); + return ta.getAssemblyFiles(context.getSession()); } } - private BuildDirs createBuildDirs(String imageName, MojoParameters params) { - BuildDirs buildDirs = new BuildDirs(imageName, params); + private BuildDirs createBuildDirs(String imageName, MavenBuildContext context) { + BuildDirs buildDirs = new BuildDirs(imageName, context); buildDirs.createDirs(); return buildDirs; } @@ -278,9 +273,9 @@ private boolean isArchive(AssemblyConfiguration assemblyConfig) { } public File createChangedFilesArchive(List entries, File assemblyDirectory, - String imageName, MojoParameters mojoParameters) - throws MojoExecutionException { - BuildDirs dirs = createBuildDirs(imageName, mojoParameters); + String imageName, MavenBuildContext context) + throws IOException { + BuildDirs dirs = createBuildDirs(imageName, context); try { File archive = new File(dirs.getTemporaryRootDirectory(), "changed-files.tar"); File archiveDir = createArchiveDir(dirs); @@ -290,8 +285,8 @@ public File createChangedFilesArchive(List entries, File as } return createChangedFilesTarBall(archive, archiveDir); } catch (IOException exp) { - throw new MojoExecutionException("Error while creating " + dirs.getTemporaryRootDirectory() + - "/changed-files.tar: " + exp); + throw new IOException("Error while creating " + dirs.getTemporaryRootDirectory() + + "/changed-files.tar: " + exp); } } @@ -303,7 +298,7 @@ private File prepareChangedFilesArchivePath(File archiveDir, File destFile, File // Create final tar-ball to be used for building the archive to send to the Docker daemon private File createBuildTarBall(BuildDirs buildDirs, List archiverCustomizers, - AssemblyConfiguration assemblyConfig, ArchiveCompression compression) throws MojoExecutionException { + AssemblyConfiguration assemblyConfig, ArchiveCompression compression) throws IOException { File archive = new File(buildDirs.getTemporaryRootDirectory(), "docker-build." + compression.getFileSuffix()); try { TarArchiver archiver = createBuildArchiver(buildDirs.getOutputDirectory(), archive, assemblyConfig); @@ -316,18 +311,18 @@ private File createBuildTarBall(BuildDirs buildDirs, List ar archiver.createArchive(); return archive; } catch (NoSuchArchiverException e) { - throw new MojoExecutionException("No archiver for type 'tar' found", e); + throw new IOException("No archiver for type 'tar' found", e); } catch (IOException e) { - throw new MojoExecutionException("Cannot create archive " + archive, e); + throw new IOException("Cannot create archive " + archive, e); } } - private void addDockerIncludesExcludesIfPresent(DefaultFileSet fileSet, MojoParameters params) throws IOException { + private void addDockerIncludesExcludesIfPresent(DefaultFileSet fileSet, MavenBuildContext params) throws IOException { addDockerExcludes(fileSet, params); addDockerIncludes(fileSet); } - private void addDockerExcludes(DefaultFileSet fileSet, MojoParameters params) throws IOException { + private void addDockerExcludes(DefaultFileSet fileSet, MavenBuildContext params) throws IOException { File directory = fileSet.getDirectory(); List excludes = new ArrayList<>(); // Output directory will be always excluded @@ -351,7 +346,7 @@ private void addDockerIncludes(DefaultFileSet fileSet) throws IOException { } } - private File createChangedFilesTarBall(File archive, File archiveDir) throws MojoExecutionException { + private File createChangedFilesTarBall(File archive, File archiveDir) throws IOException { try { TarArchiver archiver = (TarArchiver) archiverManager.getArchiver("tar"); archiver.setLongfile(TarLongFileMode.posix); @@ -360,23 +355,23 @@ private File createChangedFilesTarBall(File archive, File archiveDir) throws Moj archiver.createArchive(); return archive; } catch (NoSuchArchiverException e) { - throw new MojoExecutionException("No archiver for type 'tar' found", e); + throw new IOException("No archiver for type 'tar' found", e); } catch (IOException e) { - throw new MojoExecutionException("Cannot create archive " + archive, e); + throw new IOException("Cannot create archive " + archive, e); } catch (RuntimeException e) { e.printStackTrace(); throw e; } } - private File createArchiveDir(BuildDirs dirs) throws IOException, MojoExecutionException { + private File createArchiveDir(BuildDirs dirs) throws IOException { File archiveDir = new File(dirs.getTemporaryRootDirectory(), "changed-files"); if (archiveDir.exists()) { // Remove old stuff to FileUtils.cleanDirectory(archiveDir); } else { if (!archiveDir.mkdir()) { - throw new MojoExecutionException("Cannot create " + archiveDir); + throw new IOException("Cannot create " + archiveDir); } } return archiveDir; @@ -453,8 +448,8 @@ DockerFileBuilder createDockerFileBuilder(BuildImageConfiguration buildConfig, A return builder; } - private void createAssemblyArchive(AssemblyConfiguration assemblyConfig, MojoParameters params, BuildDirs buildDirs) - throws MojoExecutionException { + private void createAssemblyArchive(AssemblyConfiguration assemblyConfig, MavenBuildContext params, BuildDirs buildDirs) + throws IOException { DockerAssemblyConfigurationSource source = new DockerAssemblyConfigurationSource(params, buildDirs, assemblyConfig); Assembly assembly = getAssemblyConfig(assemblyConfig, source); @@ -472,11 +467,9 @@ private void createAssemblyArchive(AssemblyConfiguration assemblyConfig, MojoPar "built the artifact before with 'mvn package' (should be available in the target/ dir). " + "Please see the documentation (section \"Assembly\") for more information."; } - throw new MojoExecutionException(error, e); + throw new IOException(error, e); } catch (InvalidAssemblerConfigurationException e) { - throw new MojoExecutionException(assembly, "Assembly is incorrectly configured: " + assembly.getId(), - "Assembly: " + assembly.getId() + " is not configured correctly: " - + e.getMessage()); + throw new IOException("Assembly: " + assembly.getId() + " is not configured correctly: " + e.getMessage(), e); } finally { setArtifactFile(params.getProject(), originalArtifactFile); } @@ -524,7 +517,7 @@ private void setArtifactFile(MavenProject project, File artifactFile) { } private Assembly getAssemblyConfig(AssemblyConfiguration assemblyConfig, DockerAssemblyConfigurationSource source) - throws MojoExecutionException { + throws IOException { Assembly assembly = assemblyConfig.getInline(); if (assembly == null) { assembly = extractAssembly(source); @@ -532,20 +525,20 @@ private Assembly getAssemblyConfig(AssemblyConfiguration assemblyConfig, DockerA return assembly; } - private Assembly extractAssembly(AssemblerConfigurationSource config) throws MojoExecutionException { + private Assembly extractAssembly(AssemblerConfigurationSource config) throws IOException { try { List assemblies = assemblyReader.readAssemblies(config); if (assemblies.size() != 1) { - throw new MojoExecutionException("Only one assembly can be used for creating a Docker base image (and not " + throw new IllegalArgumentException("Only one assembly can be used for creating a Docker base image (and not " + assemblies.size() + ")"); } return assemblies.get(0); } catch (AssemblyReadException e) { - throw new MojoExecutionException("Error reading assembly: " + e.getMessage(), e); + throw new IOException("Error reading assembly: " + e.getMessage(), e); } catch (InvalidAssemblerConfigurationException e) { - throw new MojoExecutionException(assemblyReader, e.getMessage(), "Docker assembly configuration is invalid: " + e.getMessage()); + throw new IOException("Docker assembly configuration is invalid: " + e.getMessage(), e); } } diff --git a/src/main/java/io/fabric8/maven/docker/assembly/MappingTrackArchiver.java b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/MappingTrackArchiver.java similarity index 99% rename from src/main/java/io/fabric8/maven/docker/assembly/MappingTrackArchiver.java rename to src/main/java/io/fabric8/maven/docker/build/maven/assembly/MappingTrackArchiver.java index 1e939d72a..bc6261352 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/MappingTrackArchiver.java +++ b/src/main/java/io/fabric8/maven/docker/build/maven/assembly/MappingTrackArchiver.java @@ -1,4 +1,4 @@ -package io.fabric8.maven.docker.assembly;/* +package io.fabric8.maven.docker.build.maven.assembly;/* * * Copyright 2014 Roland Huss * diff --git a/src/main/java/io/fabric8/maven/docker/config/BuildImageConfiguration.java b/src/main/java/io/fabric8/maven/docker/config/BuildImageConfiguration.java index 9527dfa5c..e229de82d 100644 --- a/src/main/java/io/fabric8/maven/docker/config/BuildImageConfiguration.java +++ b/src/main/java/io/fabric8/maven/docker/config/BuildImageConfiguration.java @@ -2,20 +2,24 @@ import java.io.File; import java.io.Serializable; -import java.util.*; - -import io.fabric8.maven.docker.util.*; -import org.apache.maven.plugins.annotations.Parameter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import javax.annotation.Nonnull; +import io.fabric8.maven.docker.build.BuildContext; +import io.fabric8.maven.docker.util.DeepCopy; +import io.fabric8.maven.docker.util.EnvUtil; +import io.fabric8.maven.docker.util.Logger; +import org.apache.maven.plugins.annotations.Parameter; + /** * @author roland * @since 02.09.14 */ public class BuildImageConfiguration implements Serializable { - public static final String DEFAULT_FILTER = "${*}"; public static final String DEFAULT_CLEANUP = "try"; /** @@ -165,10 +169,6 @@ public String getDockerFileDirRaw() { } public String getFilter() { - return filter != null ? filter : DEFAULT_FILTER; - } - - public String getFilterRaw() { return filter; } @@ -235,14 +235,10 @@ public String getCommand() { return command; } - public String getCleanup() { + public String getCleanupMode() { return cleanup; } - public CleanupMode cleanupMode() { - return CleanupMode.parse(cleanup != null ? cleanup : DEFAULT_CLEANUP); - } - public boolean nocache() { return nocache != null ? nocache : false; } @@ -296,13 +292,7 @@ public Map getArgs() { return args; } - public File getAbsoluteDockerFilePath(MojoParameters mojoParams) { - return EnvUtil.prepareAbsoluteSourceDirPath(mojoParams, getDockerFile().getPath()); - } - - public File getAbsoluteDockerTarPath(MojoParameters mojoParams) { - return EnvUtil.prepareAbsoluteSourceDirPath(mojoParams, getDockerArchive().getPath()); - } + // =========================================================================================== public static class Builder { private final BuildImageConfiguration config; diff --git a/src/main/java/io/fabric8/maven/docker/config/RegistryAuthConfiguration.java b/src/main/java/io/fabric8/maven/docker/config/RegistryAuthConfiguration.java index 68364e1e4..5a39c23c4 100644 --- a/src/main/java/io/fabric8/maven/docker/config/RegistryAuthConfiguration.java +++ b/src/main/java/io/fabric8/maven/docker/config/RegistryAuthConfiguration.java @@ -4,7 +4,7 @@ import java.util.Map; import java.util.TreeMap; -import io.fabric8.maven.docker.util.AuthConfigFactory; +import io.fabric8.maven.docker.build.maven.AuthConfigFactory; import org.apache.commons.lang3.StringUtils; import org.apache.maven.plugins.annotations.Parameter; @@ -47,7 +47,7 @@ public Map toMap() { authMap.put(AuthConfigFactory.AUTH_AUTHTOKEN, authToken); } if (StringUtils.isNotBlank(email)) { - authMap.put(AuthConfigFactory.AUTH_EMAIL,email); + authMap.put(AuthConfigFactory.AUTH_EMAIL, email); } return authMap; } diff --git a/src/main/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandler.java b/src/main/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandler.java index 5fb8b2a29..d81db027d 100644 --- a/src/main/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandler.java +++ b/src/main/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandler.java @@ -127,7 +127,7 @@ private BuildImageConfiguration extractBuildConfiguration(ImageConfiguration fro return new BuildImageConfiguration.Builder() .cmd(extractArguments(valueProvider, CMD, config == null ? null : config.getCmd())) - .cleanup(valueProvider.getString(CLEANUP, config == null ? null : config.getCleanup())) + .cleanup(valueProvider.getString(CLEANUP, config == null ? null : config.getCleanupMode())) .nocache(valueProvider.getBoolean(NOCACHE, config == null ? null : config.getNoCache())) .optimise(valueProvider.getBoolean(OPTIMISE, config == null ? null : config.getOptimise())) .entryPoint(extractArguments(valueProvider, ENTRYPOINT, config == null ? null : config.getEntryPoint())) @@ -153,7 +153,7 @@ private BuildImageConfiguration extractBuildConfiguration(ImageConfiguration fro .dockerFile(valueProvider.getString(DOCKER_FILE, config == null ? null : config.getDockerFileRaw())) .dockerFileDir(valueProvider.getString(DOCKER_FILE_DIR, config == null ? null : config.getDockerFileDirRaw())) .buildOptions(valueProvider.getMap(BUILD_OPTIONS, config == null ? null : config.getBuildOptions())) - .filter(valueProvider.getString(FILTER, config == null ? null : config.getFilterRaw())) + .filter(valueProvider.getString(FILTER, config == null ? null : config.getFilter())) .user(valueProvider.getString(USER, config == null ? null : config.getUser())) .healthCheck(extractHealthCheck(config == null ? null : config.getHealthCheck(), valueProvider)) .build(); diff --git a/src/main/java/io/fabric8/maven/docker/config/handler/property/ValueProvider.java b/src/main/java/io/fabric8/maven/docker/config/handler/property/ValueProvider.java index 51ec1d158..6a1ceeca0 100644 --- a/src/main/java/io/fabric8/maven/docker/config/handler/property/ValueProvider.java +++ b/src/main/java/io/fabric8/maven/docker/config/handler/property/ValueProvider.java @@ -43,7 +43,7 @@ public class ValueProvider { private LongValueExtractor longValueExtractor; private BooleanValueExtractor booleanValueExtractor; private DoubleValueExtractor doubleValueExtractor; - + /** * Initiates ValueProvider which is to work with data from the given properties. * @@ -200,9 +200,6 @@ protected T merge(ConfigKey key, List values) { } } - - - private class StringValueExtractor extends ValueExtractor { @Override protected String withPrefix(String prefix, ConfigKey key, Properties properties) { diff --git a/src/main/java/io/fabric8/maven/docker/model/ContainerDetails.java b/src/main/java/io/fabric8/maven/docker/model/ContainerDetails.java index ec820f70f..548239149 100644 --- a/src/main/java/io/fabric8/maven/docker/model/ContainerDetails.java +++ b/src/main/java/io/fabric8/maven/docker/model/ContainerDetails.java @@ -1,16 +1,14 @@ package io.fabric8.maven.docker.model; -import com.google.common.base.Joiner; -import com.google.gson.JsonObject; - -import java.util.Calendar; +import java.time.Instant; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; -import javax.xml.bind.DatatypeConverter; +import com.google.common.base.Joiner; +import com.google.gson.JsonObject; public class ContainerDetails implements Container { @@ -47,8 +45,8 @@ public ContainerDetails(JsonObject json) { @Override public long getCreated() { String date = json.get(CREATED).getAsString(); - Calendar cal = DatatypeConverter.parseDateTime(date); - return cal.getTimeInMillis(); + Instant instant = Instant.parse(date); + return instant.toEpochMilli(); } @Override diff --git a/src/main/java/io/fabric8/maven/docker/service/BuildService.java b/src/main/java/io/fabric8/maven/docker/service/BuildService.java deleted file mode 100644 index 1d19a4782..000000000 --- a/src/main/java/io/fabric8/maven/docker/service/BuildService.java +++ /dev/null @@ -1,314 +0,0 @@ -package io.fabric8.maven.docker.service; - -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import io.fabric8.maven.docker.access.BuildOptions; -import io.fabric8.maven.docker.access.DockerAccess; -import io.fabric8.maven.docker.access.DockerAccessException; -import io.fabric8.maven.docker.assembly.DockerAssemblyManager; -import io.fabric8.maven.docker.config.AssemblyConfiguration; -import io.fabric8.maven.docker.config.BuildImageConfiguration; -import io.fabric8.maven.docker.config.CleanupMode; -import io.fabric8.maven.docker.config.ImageConfiguration; -import io.fabric8.maven.docker.util.DockerFileUtil; -import io.fabric8.maven.docker.util.EnvUtil; -import io.fabric8.maven.docker.util.ImageName; -import io.fabric8.maven.docker.util.Logger; -import io.fabric8.maven.docker.util.MojoParameters; - -import com.google.common.collect.ImmutableMap; - -import org.apache.maven.plugin.MojoExecutionException; - -public class BuildService { - - private final DockerAccess docker; - private final QueryService queryService; - private final ArchiveService archiveService; - private final RegistryService registryService; - private final Logger log; - - BuildService(DockerAccess docker, QueryService queryService, RegistryService registryService, ArchiveService archiveService, Logger log) { - this.docker = docker; - this.queryService = queryService; - this.registryService = registryService; - this.archiveService = archiveService; - this.log = log; - } - - /** - * Pull the base image if needed and run the build. - * - * @param imageConfig the image configuration - * @param buildContext the build context - * @throws DockerAccessException - * @throws MojoExecutionException - */ - public void buildImage(ImageConfiguration imageConfig, ImagePullManager imagePullManager, BuildContext buildContext) - throws DockerAccessException, MojoExecutionException { - - if (imagePullManager != null) { - autoPullBaseImage(imageConfig, imagePullManager, buildContext); - } - - buildImage(imageConfig, buildContext.getMojoParameters(), checkForNocache(imageConfig), addBuildArgs(buildContext)); - } - - public void tagImage(String imageName, ImageConfiguration imageConfig) throws DockerAccessException { - - List tags = imageConfig.getBuildConfiguration().getTags(); - if (tags.size() > 0) { - log.info("%s: Tag with %s", imageConfig.getDescription(), EnvUtil.stringJoin(tags, ",")); - - for (String tag : tags) { - if (tag != null) { - docker.tag(imageName, new ImageName(imageName, tag).getFullName(), true); - } - } - - log.debug("Tagging image successful!"); - } - } - - /** - * Build an image - * - * @param imageConfig the image configuration - * @param params mojo params for the project - * @param noCache if not null, dictate the caching behaviour. Otherwise its taken from the build configuration - * @param buildArgs - * @throws DockerAccessException - * @throws MojoExecutionException - */ - protected void buildImage(ImageConfiguration imageConfig, MojoParameters params, boolean noCache, Map buildArgs) - throws DockerAccessException, MojoExecutionException { - - String imageName = imageConfig.getName(); - ImageName.validate(imageName); - - BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); - - String oldImageId = null; - - CleanupMode cleanupMode = buildConfig.cleanupMode(); - if (cleanupMode.isRemove()) { - oldImageId = queryService.getImageId(imageName); - } - - long time = System.currentTimeMillis(); - - if (buildConfig.getDockerArchive() != null) { - docker.loadImage(imageName, buildConfig.getAbsoluteDockerTarPath(params)); - log.info("%s: Loaded tarball in %s", buildConfig.getDockerArchive(), EnvUtil.formatDurationTill(time)); - return; - } - - File dockerArchive = archiveService.createArchive(imageName, buildConfig, params, log); - log.info("%s: Created %s in %s", imageConfig.getDescription(), dockerArchive.getName(), EnvUtil.formatDurationTill(time)); - - Map mergedBuildMap = prepareBuildArgs(buildArgs, buildConfig); - - // auto is now supported by docker, consider switching? - BuildOptions opts = - new BuildOptions(buildConfig.getBuildOptions()) - .dockerfile(getDockerfileName(buildConfig)) - .forceRemove(cleanupMode.isRemove()) - .noCache(noCache) - .buildArgs(mergedBuildMap); - String newImageId = doBuildImage(imageName, dockerArchive, opts); - log.info("%s: Built image %s", imageConfig.getDescription(), newImageId); - - if (oldImageId != null && !oldImageId.equals(newImageId)) { - try { - docker.removeImage(oldImageId, true); - log.info("%s: Removed old image %s", imageConfig.getDescription(), oldImageId); - } catch (DockerAccessException exp) { - if (cleanupMode == CleanupMode.TRY_TO_REMOVE) { - log.warn("%s: %s (old image)%s", imageConfig.getDescription(), exp.getMessage(), - (exp.getCause() != null ? " [" + exp.getCause().getMessage() + "]" : "")); - } else { - throw exp; - } - } - } - } - - private Map prepareBuildArgs(Map buildArgs, BuildImageConfiguration buildConfig) { - ImmutableMap.Builder builder = ImmutableMap.builder().putAll(buildArgs); - if (buildConfig.getArgs() != null) { - builder.putAll(buildConfig.getArgs()); - } - return builder.build(); - } - - private String getDockerfileName(BuildImageConfiguration buildConfig) { - if (buildConfig.isDockerFileMode()) { - return buildConfig.getDockerFile().getName(); - } else { - return null; - } - } - - private String doBuildImage(String imageName, File dockerArchive, BuildOptions options) - throws DockerAccessException, MojoExecutionException { - docker.buildImage(imageName, dockerArchive, options); - return queryService.getImageId(imageName); - } - - private Map addBuildArgs(BuildContext buildContext) { - Map buildArgsFromProject = addBuildArgsFromProperties(buildContext.getMojoParameters().getProject().getProperties()); - Map buildArgsFromSystem = addBuildArgsFromProperties(System.getProperties()); - return ImmutableMap.builder() - .putAll(buildContext.getBuildArgs() != null ? buildContext.getBuildArgs() : Collections.emptyMap()) - .putAll(buildArgsFromProject) - .putAll(buildArgsFromSystem) - .build(); - } - - private Map addBuildArgsFromProperties(Properties properties) { - String argPrefix = "docker.buildArg."; - Map buildArgs = new HashMap<>(); - for (Object keyObj : properties.keySet()) { - String key = (String) keyObj; - if (key.startsWith(argPrefix)) { - String argKey = key.replaceFirst(argPrefix, ""); - String value = properties.getProperty(key); - - if (!isEmpty(value)) { - buildArgs.put(argKey, value); - } - } - } - log.debug("Build args set %s", buildArgs); - return buildArgs; - } - - private void autoPullBaseImage(ImageConfiguration imageConfig, ImagePullManager imagePullManager, BuildContext buildContext) - throws DockerAccessException, MojoExecutionException { - BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); - - if (buildConfig.getDockerArchive() != null) { - // No auto pull needed in archive mode - return; - } - - String fromImage; - if (buildConfig.isDockerFileMode()) { - fromImage = extractBaseFromDockerfile(buildConfig, buildContext); - } else { - fromImage = extractBaseFromConfiguration(buildConfig); - } - if (fromImage != null && !DockerAssemblyManager.SCRATCH_IMAGE.equals(fromImage)) { - registryService.pullImageWithPolicy(fromImage, imagePullManager, buildContext.getRegistryConfig(), queryService.hasImage(fromImage)); - } - } - - private String extractBaseFromConfiguration(BuildImageConfiguration buildConfig) { - String fromImage; - fromImage = buildConfig.getFrom(); - if (fromImage == null) { - AssemblyConfiguration assemblyConfig = buildConfig.getAssemblyConfiguration(); - if (assemblyConfig == null) { - fromImage = DockerAssemblyManager.DEFAULT_DATA_BASE_IMAGE; - } - } - return fromImage; - } - - private String extractBaseFromDockerfile(BuildImageConfiguration buildConfig, BuildContext buildContext) { - String fromImage; - try { - File fullDockerFilePath = buildConfig.getAbsoluteDockerFilePath(buildContext.getMojoParameters()); - fromImage = DockerFileUtil.extractBaseImage( - fullDockerFilePath, - DockerFileUtil.createInterpolator(buildContext.getMojoParameters(), buildConfig.getFilter())); - } catch (IOException e) { - // Cant extract base image, so we wont try an auto pull. An error will occur later anyway when - // building the image, so we are passive here. - fromImage = null; - } - return fromImage; - } - - private boolean checkForNocache(ImageConfiguration imageConfig) { - String nocache = System.getProperty("docker.nocache"); - if (nocache != null) { - return nocache.length() == 0 || Boolean.valueOf(nocache); - } else { - BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); - return buildConfig.nocache(); - } - } - - private boolean isEmpty(String str) { - return str == null || str.isEmpty(); - } - - - // =========================================== - - - public static class BuildContext implements Serializable { - - private MojoParameters mojoParameters; - - private Map buildArgs; - - private RegistryService.RegistryConfig registryConfig; - - public BuildContext() { - } - - public MojoParameters getMojoParameters() { - return mojoParameters; - } - - public Map getBuildArgs() { - return buildArgs; - } - - public RegistryService.RegistryConfig getRegistryConfig() { - return registryConfig; - } - - public static class Builder { - - private BuildContext context; - - public Builder() { - this.context = new BuildContext(); - } - - public Builder(BuildContext context) { - this.context = context; - } - - public Builder mojoParameters(MojoParameters mojoParameters) { - context.mojoParameters = mojoParameters; - return this; - } - - public Builder buildArgs(Map buildArgs) { - context.buildArgs = buildArgs; - return this; - } - - public Builder registryConfig(RegistryService.RegistryConfig registryConfig) { - context.registryConfig = registryConfig; - return this; - } - - public BuildContext build() { - return context; - } - } - } - -} diff --git a/src/main/java/io/fabric8/maven/docker/service/ImagePullManager.java b/src/main/java/io/fabric8/maven/docker/service/ImagePullManager.java deleted file mode 100644 index ee27616ae..000000000 --- a/src/main/java/io/fabric8/maven/docker/service/ImagePullManager.java +++ /dev/null @@ -1,114 +0,0 @@ -package io.fabric8.maven.docker.service; - -import com.google.gson.JsonObject; - -import io.fabric8.maven.docker.config.ImagePullPolicy; -import io.fabric8.maven.docker.util.AutoPullMode; -import io.fabric8.maven.docker.util.JsonFactory; - -/** - * Simple interface for a ImagePullCache manager, to load and persist the cache. - */ -public class ImagePullManager { - - // Key for the previously used image cache - private static final String CONTEXT_KEY_PREVIOUSLY_PULLED = "CONTEXT_KEY_PREVIOUSLY_PULLED"; - - // image pull policy - private final ImagePullPolicy imagePullPolicy; - - private CacheStore cacheStore; - - public ImagePullManager(CacheStore cacheStore, String imagePullPolicy, String autoPull) { - this.cacheStore = cacheStore; - this.imagePullPolicy = createPullPolicy(imagePullPolicy, autoPull); - } - - ImagePullPolicy getImagePullPolicy() { - return imagePullPolicy; - } - - public ImagePullPolicy createPullPolicy(String imagePullPolicy, String autoPull) { - if (imagePullPolicy != null) { - return ImagePullPolicy.fromString(imagePullPolicy); - } - if (autoPull != null) { - AutoPullMode autoPullMode = AutoPullMode.fromString(autoPull); - switch(autoPullMode) { - case OFF: - return ImagePullPolicy.Never; - case ALWAYS: - return ImagePullPolicy.Always; - case ON: - case ONCE: - return ImagePullPolicy.IfNotPresent; - } - } - return ImagePullPolicy.IfNotPresent; - } - - public boolean hasAlreadyPulled(String image) { - return load().has(image); - } - - public void pulled(String image) { - save(load().add(image)); - } - - - public interface CacheStore { - String get(String key); - - void put(String key, String value); - } - - public ImagePullCache load() { - - String pullCacheJson = cacheStore.get(CONTEXT_KEY_PREVIOUSLY_PULLED); - - ImagePullCache cache = new ImagePullCache(pullCacheJson); - - if (pullCacheJson == null) { - save(cache); - cacheStore.put(CONTEXT_KEY_PREVIOUSLY_PULLED, cache.toString()); - } - return cache; - } - - public void save(ImagePullCache cache) { - cacheStore.put(CONTEXT_KEY_PREVIOUSLY_PULLED, cache.toString()); - } - - /** - * Simple serializable cache for holding image names - * - * @author roland - * @since 20/07/16 - */ - class ImagePullCache { - - private JsonObject cache; - - public ImagePullCache() { - this(null); - } - - public ImagePullCache(String json) { - cache = json != null ? JsonFactory.newJsonObject(json) : new JsonObject(); - } - - public boolean has(String imageName) { - return cache.has(imageName); - } - - public ImagePullCache add(String image) { - cache.addProperty(image, Boolean.TRUE); - return this; - } - - @Override - public String toString() { - return cache.toString(); - } - } -} diff --git a/src/main/java/io/fabric8/maven/docker/service/RegistryService.java b/src/main/java/io/fabric8/maven/docker/service/RegistryService.java deleted file mode 100644 index 64bde1f78..000000000 --- a/src/main/java/io/fabric8/maven/docker/service/RegistryService.java +++ /dev/null @@ -1,228 +0,0 @@ -package io.fabric8.maven.docker.service; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Map; - -import io.fabric8.maven.docker.access.AuthConfig; -import io.fabric8.maven.docker.access.DockerAccess; -import io.fabric8.maven.docker.access.DockerAccessException; -import io.fabric8.maven.docker.config.BuildImageConfiguration; -import io.fabric8.maven.docker.config.ImageConfiguration; -import io.fabric8.maven.docker.config.ImagePullPolicy; -import io.fabric8.maven.docker.util.AuthConfigFactory; -import io.fabric8.maven.docker.util.EnvUtil; -import io.fabric8.maven.docker.util.ImageName; -import io.fabric8.maven.docker.util.Logger; - -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.settings.Settings; - -/** - * Allows to interact with registries, eg. to push/pull images. - */ -public class RegistryService { - - private final DockerAccess docker; - private final Logger log; - - RegistryService(DockerAccess docker, Logger log) { - this.docker = docker; - this.log = log; - } - - /** - * Push a set of images to a registry - * - * @param imageConfigs images to push (but only if they have a build configuration) - * @param retries how often to retry - * @param registryConfig a global registry configuration - * @param skipTag flag to skip pushing tagged images - * @throws DockerAccessException - * @throws MojoExecutionException - */ - public void pushImages(Collection imageConfigs, - int retries, RegistryConfig registryConfig, boolean skipTag) throws DockerAccessException, MojoExecutionException { - for (ImageConfiguration imageConfig : imageConfigs) { - BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); - String name = imageConfig.getName(); - if (buildConfig != null) { - String configuredRegistry = EnvUtil.firstRegistryOf( - new ImageName(imageConfig.getName()).getRegistry(), - imageConfig.getRegistry(), - registryConfig.getRegistry()); - - - AuthConfig authConfig = createAuthConfig(true, new ImageName(name).getUser(), configuredRegistry, registryConfig); - - long start = System.currentTimeMillis(); - docker.pushImage(name, authConfig, configuredRegistry, retries); - log.info("Pushed %s in %s", name, EnvUtil.formatDurationTill(start)); - - if (!skipTag) { - for (String tag : imageConfig.getBuildConfiguration().getTags()) { - if (tag != null) { - docker.pushImage(new ImageName(name, tag).getFullName(), authConfig, configuredRegistry, retries); - } - } - } - } - } - } - - - /** - * Check an image, and, if autoPull is set to true, fetch it. Otherwise if the image - * is not existent, throw an error - * @param registryConfig registry configuration - * - * @throws DockerAccessException - * @throws MojoExecutionException - */ - public void pullImageWithPolicy(String image, ImagePullManager pullManager, RegistryConfig registryConfig, boolean hasImage) - throws DockerAccessException, MojoExecutionException { - - // Already pulled, so we don't need to take care - if (pullManager.hasAlreadyPulled(image)) { - return; - } - - // Check if a pull is required - if (!imageRequiresPull(hasImage, pullManager.getImagePullPolicy(), image)) { - return; - } - - ImageName imageName = new ImageName(image); - long time = System.currentTimeMillis(); - String actualRegistry = EnvUtil.firstRegistryOf( - imageName.getRegistry(), - registryConfig.getRegistry()); - docker.pullImage(imageName.getFullName(), - createAuthConfig(false, null, actualRegistry, registryConfig), actualRegistry); - log.info("Pulled %s in %s", imageName.getFullName(), EnvUtil.formatDurationTill(time)); - pullManager.pulled(image); - - if (actualRegistry != null && !imageName.hasRegistry()) { - // If coming from a registry which was not contained in the original name, add a tag from the - // full name with the registry to the short name with no-registry. - docker.tag(imageName.getFullName(actualRegistry), image, false); - } - } - - - // ============================================================================================================ - - - private boolean imageRequiresPull(boolean hasImage, ImagePullPolicy pullPolicy, String imageName) - throws MojoExecutionException { - - // The logic here is like this (see also #96): - // otherwise: don't pull - - if (pullPolicy == ImagePullPolicy.Never) { - if (!hasImage) { - throw new MojoExecutionException( - String.format("No image '%s' found and pull policy 'Never' is set. Please chose another pull policy or pull the image yourself)", imageName)); - } - return false; - } - - // If the image is not available and mode is not ImagePullPolicy.Never --> pull - if (!hasImage) { - return true; - } - - // If pullPolicy == Always --> pull, otherwise not (we have it already) - return pullPolicy == ImagePullPolicy.Always; - } - - private AuthConfig createAuthConfig(boolean isPush, String user, String registry, RegistryConfig config) - throws MojoExecutionException { - - return config.getAuthConfigFactory().createAuthConfig( - isPush, config.isSkipExtendedAuth(), config.getAuthConfig(), - config.getSettings(), user, registry); - } - - // =========================================== - - - public static class RegistryConfig implements Serializable { - - private String registry; - - private Settings settings; - - private AuthConfigFactory authConfigFactory; - - private boolean skipExtendedAuth; - - private Map authConfig; - - public RegistryConfig() { - } - - public String getRegistry() { - return registry; - } - - public Settings getSettings() { - return settings; - } - - public AuthConfigFactory getAuthConfigFactory() { - return authConfigFactory; - } - - public boolean isSkipExtendedAuth() { - return skipExtendedAuth; - } - - public Map getAuthConfig() { - return authConfig; - } - - public static class Builder { - - private RegistryConfig context = new RegistryConfig(); - - public Builder() { - this.context = new RegistryConfig(); - } - - public Builder(RegistryConfig context) { - this.context = context; - } - - public Builder registry(String registry) { - context.registry = registry; - return this; - } - - public Builder settings(Settings settings) { - context.settings = settings; - return this; - } - - public Builder authConfigFactory(AuthConfigFactory authConfigFactory) { - context.authConfigFactory = authConfigFactory; - return this; - } - - public Builder skipExtendedAuth(boolean skipExtendedAuth) { - context.skipExtendedAuth = skipExtendedAuth; - return this; - } - - public Builder authConfig(Map authConfig) { - context.authConfig = authConfig; - return this; - } - - public RegistryConfig build() { - return context; - } - } - } - -} diff --git a/src/main/java/io/fabric8/maven/docker/service/ServiceHub.java b/src/main/java/io/fabric8/maven/docker/service/ServiceHub.java index 404a03310..c86f7b67e 100644 --- a/src/main/java/io/fabric8/maven/docker/service/ServiceHub.java +++ b/src/main/java/io/fabric8/maven/docker/service/ServiceHub.java @@ -17,7 +17,11 @@ package io.fabric8.maven.docker.service; import io.fabric8.maven.docker.access.DockerAccess; -import io.fabric8.maven.docker.assembly.DockerAssemblyManager; +import io.fabric8.maven.docker.build.maven.assembly.DockerAssemblyManager; +import io.fabric8.maven.docker.build.docker.DockerBuildService; +import io.fabric8.maven.docker.build.docker.DockerRegistryService; +import io.fabric8.maven.docker.build.maven.MavenArchiveService; +import io.fabric8.maven.docker.build.maven.MavenCacheBackend; import io.fabric8.maven.docker.log.LogOutputSpecFactory; import io.fabric8.maven.docker.util.Logger; @@ -38,10 +42,10 @@ public class ServiceHub { private final QueryService queryService; private final RunService runService; - private final RegistryService registryService; - private final BuildService buildService; + private final DockerRegistryService registryService; + private final DockerBuildService buildService; private final MojoExecutionService mojoExecutionService; - private final ArchiveService archiveService; + private final MavenArchiveService archiveService; private final VolumeService volumeService; private final WatchService watchService; private final WaitService waitService; @@ -53,13 +57,13 @@ public class ServiceHub { this.dockerAccess = dockerAccess; mojoExecutionService = new MojoExecutionService(project, session, pluginManager); - archiveService = new ArchiveService(dockerAssemblyManager, logger); + archiveService = new MavenArchiveService(dockerAssemblyManager, logger); if (dockerAccess != null) { queryService = new QueryService(dockerAccess); - registryService = new RegistryService(dockerAccess, logger); + registryService = new DockerRegistryService(dockerAccess, logger, new MavenCacheBackend(session)); runService = new RunService(dockerAccess, queryService, containerTracker, logSpecFactory, logger); - buildService = new BuildService(dockerAccess, queryService, registryService, archiveService, logger); + buildService = new DockerBuildService(dockerAccess, registryService, logger); volumeService = new VolumeService(dockerAccess); watchService = new WatchService(archiveService, buildService, dockerAccess, mojoExecutionService, queryService, runService, logger); waitService = new WaitService(dockerAccess, queryService, logger); @@ -89,7 +93,7 @@ public DockerAccess getDockerAccess() { * * @return get the build service */ - public BuildService getBuildService() { + public DockerBuildService getBuildService() { checkDockerAccessInitialization(); return buildService; } @@ -109,7 +113,7 @@ public QueryService getQueryService() { * * @return query service */ - public RegistryService getRegistryService() { + public DockerRegistryService getRegistryService() { checkDockerAccessInitialization(); return registryService; } @@ -161,7 +165,7 @@ public WaitService getWaitService() { * * @return the archive service */ - public ArchiveService getArchiveService() { + public MavenArchiveService getArchiveService() { return archiveService; } diff --git a/src/main/java/io/fabric8/maven/docker/service/ServiceHubFactory.java b/src/main/java/io/fabric8/maven/docker/service/ServiceHubFactory.java index 06dbc24e5..2f50f90c8 100644 --- a/src/main/java/io/fabric8/maven/docker/service/ServiceHubFactory.java +++ b/src/main/java/io/fabric8/maven/docker/service/ServiceHubFactory.java @@ -1,7 +1,7 @@ package io.fabric8.maven.docker.service; import io.fabric8.maven.docker.access.DockerAccess; -import io.fabric8.maven.docker.assembly.DockerAssemblyManager; +import io.fabric8.maven.docker.build.maven.assembly.DockerAssemblyManager; import io.fabric8.maven.docker.util.Logger; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.BuildPluginManager; diff --git a/src/main/java/io/fabric8/maven/docker/service/WatchService.java b/src/main/java/io/fabric8/maven/docker/service/WatchService.java index 5c12c8fd7..c288d12ea 100644 --- a/src/main/java/io/fabric8/maven/docker/service/WatchService.java +++ b/src/main/java/io/fabric8/maven/docker/service/WatchService.java @@ -6,6 +6,8 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.Properties; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -15,15 +17,17 @@ import io.fabric8.maven.docker.access.DockerAccessException; import io.fabric8.maven.docker.access.ExecException; import io.fabric8.maven.docker.access.PortMapping; -import io.fabric8.maven.docker.assembly.AssemblyFiles; +import io.fabric8.maven.docker.build.maven.assembly.AssemblyFiles; +import io.fabric8.maven.docker.build.docker.DockerBuildService; +import io.fabric8.maven.docker.build.maven.MavenArchiveService; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import io.fabric8.maven.docker.config.ImageConfiguration; import io.fabric8.maven.docker.config.WatchImageConfiguration; import io.fabric8.maven.docker.config.WatchMode; import io.fabric8.maven.docker.log.LogDispatcher; import io.fabric8.maven.docker.service.helper.StartContainerExecutor; -import io.fabric8.maven.docker.util.Logger; -import io.fabric8.maven.docker.util.MojoParameters; import io.fabric8.maven.docker.util.GavLabel; +import io.fabric8.maven.docker.util.Logger; import io.fabric8.maven.docker.util.StartOrderResolver; import io.fabric8.maven.docker.util.Task; import org.apache.maven.plugin.MojoExecutionException; @@ -35,15 +39,15 @@ */ public class WatchService { - private final ArchiveService archiveService; - private final BuildService buildService; + private final MavenArchiveService archiveService; + private final DockerBuildService buildService; private final DockerAccess dockerAccess; private final MojoExecutionService mojoExecutionService; private final QueryService queryService; private final RunService runService; private final Logger log; - public WatchService(ArchiveService archiveService, BuildService buildService, DockerAccess dockerAccess, MojoExecutionService mojoExecutionService, QueryService queryService, RunService + public WatchService(MavenArchiveService archiveService, DockerBuildService buildService, DockerAccess dockerAccess, MojoExecutionService mojoExecutionService, QueryService queryService, RunService runService, Logger log) { this.archiveService = archiveService; this.buildService = buildService; @@ -54,8 +58,8 @@ public WatchService(ArchiveService archiveService, BuildService buildService, Do this.log = log; } - public synchronized void watch(WatchContext context, BuildService.BuildContext buildContext, List images) throws DockerAccessException, - MojoExecutionException { + public synchronized void watch(WatchContext watchContext, MavenBuildContext buildContext, List images) throws DockerAccessException, + IOException { // Important to be be a single threaded scheduler since watch jobs must run serialized ScheduledExecutorService executor = null; @@ -68,7 +72,7 @@ public synchronized void watch(WatchContext context, BuildService.BuildContext b String imageId = queryService.getImageId(imageConfig.getName()); String containerId = runService.lookupContainer(imageConfig.getName()); - ImageWatcher watcher = new ImageWatcher(imageConfig, context, imageId, containerId); + ImageWatcher watcher = new ImageWatcher(imageConfig, watchContext, imageId, containerId); long interval = watcher.getInterval(); WatchMode watchMode = watcher.getWatchMode(imageConfig); @@ -80,12 +84,12 @@ public synchronized void watch(WatchContext context, BuildService.BuildContext b imageConfig.getBuildConfiguration().getAssemblyConfiguration() != null) { if (watcher.isCopy()) { String containerBaseDir = imageConfig.getBuildConfiguration().getAssemblyConfiguration().getTargetDir(); - schedule(executor, createCopyWatchTask(watcher, context.getMojoParameters(), containerBaseDir), interval); + schedule(executor, createCopyWatchTask(watcher, buildContext, containerBaseDir), interval); tasks.add("copying artifacts"); } if (watcher.isBuild()) { - schedule(executor, createBuildWatchTask(watcher, context.getMojoParameters(), watchMode == WatchMode.both, buildContext), interval); + schedule(executor, createBuildWatchTask(watcher, watchMode == WatchMode.both, buildContext), interval); tasks.add("rebuilding"); } } @@ -100,8 +104,8 @@ public synchronized void watch(WatchContext context, BuildService.BuildContext b } } log.info("Waiting ..."); - if (!context.isKeepRunning()) { - runService.addShutdownHookForStoppingContainers(context.isKeepContainer(), context.isRemoveVolumes(), context.isAutoCreateCustomNetworks()); + if (!watchContext.isKeepRunning()) { + runService.addShutdownHookForStoppingContainers(watchContext.isKeepContainer(), watchContext.isRemoveVolumes(), watchContext.isAutoCreateCustomNetworks()); } wait(); } catch (InterruptedException e) { @@ -118,10 +122,10 @@ private void schedule(ScheduledExecutorService executor, Runnable runnable, long } private Runnable createCopyWatchTask(final ImageWatcher watcher, - final MojoParameters mojoParameters, final String containerBaseDir) throws MojoExecutionException { + final MavenBuildContext buildContext, final String containerBaseDir) throws IOException { final ImageConfiguration imageConfig = watcher.getImageConfiguration(); - final AssemblyFiles files = archiveService.getAssemblyFiles(imageConfig, mojoParameters); + final AssemblyFiles files = archiveService.getAssemblyFiles(imageConfig, buildContext); return new Runnable() { @Override public void run() { @@ -131,10 +135,10 @@ public void run() { log.info("%s: Assembly changed. Copying changed files to container ...", imageConfig.getDescription()); File changedFilesArchive = archiveService.createChangedFilesArchive(entries, files.getAssemblyDirectory(), - imageConfig.getName(), mojoParameters); + imageConfig.getName(), buildContext); dockerAccess.copyArchive(watcher.getContainerId(), changedFilesArchive, containerBaseDir); callPostExec(watcher); - } catch (MojoExecutionException | IOException | ExecException e) { + } catch (IOException | ExecException e) { log.error("%s: Error when copying files to container %s: %s", imageConfig.getDescription(), watcher.getContainerId(), e.getMessage()); } @@ -150,47 +154,42 @@ private void callPostExec(ImageWatcher watcher) throws DockerAccessException, Ex } } - private Runnable createBuildWatchTask(final ImageWatcher watcher, - final MojoParameters mojoParameters, final boolean doRestart, final BuildService.BuildContext buildContext) - throws MojoExecutionException { + private Runnable createBuildWatchTask(final ImageWatcher watcher, final boolean doRestart, final MavenBuildContext buildContext) + throws IOException { final ImageConfiguration imageConfig = watcher.getImageConfiguration(); - final AssemblyFiles files = archiveService.getAssemblyFiles(imageConfig, mojoParameters); + final AssemblyFiles files = archiveService.getAssemblyFiles(imageConfig, buildContext); if (files.isEmpty()) { log.error("No assembly files for %s. Are you sure you invoked together with the `package` goal?", imageConfig.getDescription()); - throw new MojoExecutionException("No files to watch found for " + imageConfig); + throw new IllegalArgumentException("No files to watch found for " + imageConfig); } - return new Runnable() { - @Override - public void run() { - List entries = files.getUpdatedEntriesAndRefresh(); - if (entries != null && entries.size() > 0) { - try { - log.info("%s: Assembly changed. Rebuild ...", imageConfig.getDescription()); + return () -> { + List entries = files.getUpdatedEntriesAndRefresh(); + if (entries != null && entries.size() > 0) { + try { + log.info("%s: Assembly changed. Rebuild ...", imageConfig.getDescription()); - if (watcher.getWatchContext().getImageCustomizer() != null) { - log.info("%s: Customizing the image ...", imageConfig.getDescription()); - watcher.getWatchContext().getImageCustomizer().execute(imageConfig); - } + if (watcher.getWatchContext().getImageCustomizer() != null) { + log.info("%s: Customizing the image ...", imageConfig.getDescription()); + watcher.getWatchContext().getImageCustomizer().execute(imageConfig); + } - buildService.buildImage(imageConfig, null, buildContext); + buildService.buildImage(imageConfig, buildContext, watcher.getWatchContext().getBuildArgs()); - String name = imageConfig.getName(); - watcher.setImageId(queryService.getImageId(name)); - if (doRestart) { - restartContainer(watcher); - } - callPostGoal(watcher); - } catch (Exception e) { - log.error("%s: Error when rebuilding - %s", imageConfig.getDescription(), e); + String name = imageConfig.getName(); + watcher.setImageId(queryService.getImageId(name)); + if (doRestart) { + restartContainer(watcher); } + callPostGoal(watcher); + } catch (Exception e) { + log.error("%s: Error when rebuilding - %s", imageConfig.getDescription(), e); } } }; } - private Runnable createRestartWatchTask(final ImageWatcher watcher) - throws DockerAccessException { + private Runnable createRestartWatchTask(final ImageWatcher watcher) { final String imageName = watcher.getImageName(); @@ -226,7 +225,8 @@ private Task defaultContainerRestartTask() { return watcher -> { // Stop old one ImageConfiguration imageConfig = watcher.getImageConfiguration(); - PortMapping mappedPorts = runService.createPortMapping(imageConfig.getRunConfiguration(), watcher.getWatchContext().getMojoParameters().getProject().getProperties()); + PortMapping mappedPorts = runService.createPortMapping(imageConfig.getRunConfiguration(), + watcher.getWatchContext().getProperties()); String id = watcher.getContainerId(); String optionalPreStop = getPreStopCommand(imageConfig); @@ -242,8 +242,8 @@ private Task defaultContainerRestartTask() { .log(log) .portMapping(mappedPorts) .gavLabel(watcher.watchContext.getGavLabel()) - .projectProperties(watcher.watchContext.mojoParameters.getProject().getProperties()) - .basedir(watcher.watchContext.mojoParameters.getProject().getBasedir()) + .projectProperties(watcher.watchContext.getProperties()) + .basedir(watcher.watchContext.getBasedir()) .imageConfig(imageConfig) .serviceHub(watcher.watchContext.hub) .logOutputSpecFactory(watcher.watchContext.serviceHubFactory.getLogOutputSpecFactory()) @@ -388,8 +388,6 @@ private WatchMode getWatchMode(ImageConfiguration imageConfig) { */ public static class WatchContext implements Serializable { - private MojoParameters mojoParameters; - private WatchMode watchMode; private int watchInterval; @@ -421,14 +419,13 @@ public static class WatchContext implements Serializable { private Date buildTimestamp; private String containerNamePattern; + private Map buildArgs; + private Properties properties; + private File basedir; public WatchContext() { } - public MojoParameters getMojoParameters() { - return mojoParameters; - } - public WatchMode getWatchMode() { return watchMode; } @@ -481,6 +478,18 @@ public String getContainerNamePattern() { return containerNamePattern; } + public Map getBuildArgs() { + return buildArgs; + } + + public Properties getProperties() { + return properties; + } + + public File getBasedir() { + return basedir; + } + public static class Builder { private WatchContext context; @@ -493,11 +502,6 @@ public Builder(WatchContext context) { this.context = context; } - public Builder mojoParameters(MojoParameters mojoParameters) { - context.mojoParameters = mojoParameters; - return this; - } - public Builder watchMode(WatchMode watchMode) { context.watchMode = watchMode; return this; @@ -573,7 +577,17 @@ public Builder serviceHubFactory(ServiceHubFactory serviceHubFactory){ return this; } - public Builder dispatcher(LogDispatcher dispatcher){ + public Builder properties(Properties properties) { + context.properties = properties; + return this; + } + + public Builder basedir(File basedir) { + context.basedir = basedir; + return this; + } + + public Builder dispatcher(LogDispatcher dispatcher) { context.dispatcher = dispatcher; return this; } @@ -588,6 +602,10 @@ public Builder containerNamePattern(String containerNamePattern) { return this; } + public Builder buildArgs(Map buildArgs) { + context.buildArgs = buildArgs; + return this; + } public WatchContext build() { return context; diff --git a/src/main/java/io/fabric8/maven/docker/util/CredentialHelperClient.java b/src/main/java/io/fabric8/maven/docker/util/CredentialHelperClient.java index 40f1c22bf..73e32370e 100644 --- a/src/main/java/io/fabric8/maven/docker/util/CredentialHelperClient.java +++ b/src/main/java/io/fabric8/maven/docker/util/CredentialHelperClient.java @@ -28,15 +28,15 @@ public String getName() { return credentialHelperName; } - public String getVersion() throws MojoExecutionException { + public String getVersion() { try { return new VersionCommand().getVersion(); } catch (IOException e) { - throw new MojoExecutionException("Error getting the version of the configured credential helper",e); + throw new RuntimeException("Error getting the version of the configured credential helper",e); } } - public AuthConfig getAuthConfig(String registryToLookup) throws MojoExecutionException { + public AuthConfig getAuthConfig(String registryToLookup) { try { JsonObject creds = new GetCommand().getCredentialNode(registryToLookup); if (creds == null) { @@ -44,7 +44,7 @@ public AuthConfig getAuthConfig(String registryToLookup) throws MojoExecutionExc } return toAuthConfig(creds); } catch (IOException e) { - throw new MojoExecutionException("Error getting the credentials for " + registryToLookup + " from the configured credential helper",e); + throw new RuntimeException("Error getting the credentials for " + registryToLookup + " from the configured credential helper",e); } } diff --git a/src/main/java/io/fabric8/maven/docker/util/DockerFileUtil.java b/src/main/java/io/fabric8/maven/docker/util/DockerFileUtil.java index 384abf6a1..26796fc52 100644 --- a/src/main/java/io/fabric8/maven/docker/util/DockerFileUtil.java +++ b/src/main/java/io/fabric8/maven/docker/util/DockerFileUtil.java @@ -18,14 +18,16 @@ import java.io.*; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import org.apache.maven.plugins.assembly.interpolation.AssemblyInterpolator; import org.apache.maven.plugins.assembly.io.DefaultAssemblyReader; import org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator; -import io.fabric8.maven.docker.assembly.DockerAssemblyConfigurationSource; +import io.fabric8.maven.docker.build.maven.assembly.DockerAssemblyConfigurationSource; /** @@ -42,9 +44,8 @@ private DockerFileUtil() {} * taken. * * @param dockerFile file from where to extract the base image - * @param interpolator interpolator for replacing properties */ - public static String extractBaseImage(File dockerFile, FixedStringSearchInterpolator interpolator) throws IOException { + public static String extractBaseImage(File dockerFile, Function interpolator) throws IOException { List fromLines = extractLines(dockerFile, "FROM", interpolator); if (!fromLines.isEmpty()) { String[] parts = fromLines.get(0); @@ -60,15 +61,14 @@ public static String extractBaseImage(File dockerFile, FixedStringSearchInterpol * * @param dockerFile dockerfile to examine * @param keyword keyword to extract the lines for - * @param interpolator interpolator for replacing properties * @return list of matched lines or an empty list */ - public static List extractLines(File dockerFile, String keyword, FixedStringSearchInterpolator interpolator) throws IOException { + public static List extractLines(File dockerFile, String keyword, Function interpolator) throws IOException { List ret = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new FileReader(dockerFile))) { String line; while ((line = reader.readLine()) != null) { - String lineInterpolated = interpolator.interpolate(line); + String lineInterpolated = interpolator.apply(line); String[] lineParts = lineInterpolated.split("\\s+"); if (lineParts.length > 0 && lineParts[0].equalsIgnoreCase(keyword)) { ret.add(lineParts); @@ -100,29 +100,32 @@ public static String interpolate(File dockerFile, FixedStringSearchInterpolator /** * Create an interpolator for the given maven parameters and filter configuration. * - * @param params The maven parameters. + * @param ctx The maven parameters. * @param filter The filter configuration. * @return An interpolator for replacing maven properties. */ - public static FixedStringSearchInterpolator createInterpolator(MojoParameters params, String filter) { + public static FixedStringSearchInterpolator createInterpolator(MavenBuildContext ctx, String filter) { String[] delimiters = extractDelimiters(filter); if (delimiters == null) { // Don't interpolate anything return FixedStringSearchInterpolator.create(); } - DockerAssemblyConfigurationSource configSource = new DockerAssemblyConfigurationSource(params, null, null); + DockerAssemblyConfigurationSource configSource = new DockerAssemblyConfigurationSource(ctx, null, null); // Patterned after org.apache.maven.plugins.assembly.interpolation.AssemblyExpressionEvaluator return AssemblyInterpolator - .fullInterpolator(params.getProject(), - DefaultAssemblyReader.createProjectInterpolator(params.getProject()) + .fullInterpolator(ctx.getProject(), + DefaultAssemblyReader.createProjectInterpolator(ctx.getProject()) .withExpressionMarkers(delimiters[0], delimiters[1]), configSource) .withExpressionMarkers(delimiters[0], delimiters[1]); } private static String[] extractDelimiters(String filter) { - if (filter == null || - filter.equalsIgnoreCase("false") || + if (filter == null) { + // Default interpolation scheme + return new String[] { "${", "}" }; + } + if (filter.equalsIgnoreCase("false") || filter.equalsIgnoreCase("none")) { return null; } diff --git a/src/main/java/io/fabric8/maven/docker/util/EnvUtil.java b/src/main/java/io/fabric8/maven/docker/util/EnvUtil.java index f491e2a40..05bf87ece 100644 --- a/src/main/java/io/fabric8/maven/docker/util/EnvUtil.java +++ b/src/main/java/io/fabric8/maven/docker/util/EnvUtil.java @@ -5,12 +5,18 @@ import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; -import com.google.common.base.*; +import com.google.common.base.Predicates; +import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import io.fabric8.maven.docker.build.BuildContext; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.apache.maven.shared.utils.io.FileUtils; @@ -86,16 +92,13 @@ public static boolean greaterOrEqualsVersion(String versionA, String versionB) { return largerVersion != null && largerVersion.equals(versionA); } - private static final Function SPLIT_ON_LAST_COLON = new Function() { - @Override - public String[] apply(String element) { - int colon = element.lastIndexOf(':'); - if (colon < 0) { - return new String[] {element, element}; - } else { - return new String[] {element.substring(0, colon), element.substring(colon + 1)}; - } - } + private static final Function SPLIT_ON_LAST_COLON = element -> { + int colon = element.lastIndexOf(':'); + if (colon < 0) { + return new String[] {element, element}; + } else { + return new String[] {element.substring(0, colon), element.substring(colon + 1)}; + } }; /** @@ -107,35 +110,14 @@ public String[] apply(String element) { * @return return list of 2-element arrays or an empty list if the given list is empty or null */ public static List splitOnLastColon(List listToSplit) { - if (listToSplit != null) { - return Lists.transform(listToSplit, SPLIT_ON_LAST_COLON); + if (listToSplit == null) { + return Collections.emptyList(); } - return Collections.emptyList(); + return listToSplit.stream().map(SPLIT_ON_LAST_COLON).collect(Collectors.toList()); } - private static final Function> COMMA_SPLITTER = new Function>() { - private Splitter COMMA_SPLIT = Splitter.on(",").trimResults().omitEmptyStrings(); - - @Override - public Iterable apply(String input) { - return COMMA_SPLIT.split(input); - } - }; - - private static final Predicate NOT_EMPTY = new Predicate() { - @Override - public boolean apply(@Nullable String s) { - return s!=null && !s.isEmpty(); - } - }; - - private static final Function TRIM = new Function() { - @Nullable - @Override - public String apply(@Nullable String s) { - return s!=null ?s.trim() :s; - } - }; + private static final Predicate NOT_EMPTY = s -> s != null && !s.isEmpty(); + private static final Function TRIM = s -> s != null ?s.trim() :s; /** * Remove empty members of a list. @@ -144,26 +126,26 @@ public String apply(@Nullable String s) { */ @Nonnull public static List removeEmptyEntries(@Nullable List input) { - if(input==null) { + if (input == null) { return Collections.emptyList(); } - Iterable trimmedInputs = Iterables.transform(input, TRIM); - Iterable nonEmptyInputs = Iterables.filter(trimmedInputs, NOT_EMPTY); - return Lists.newArrayList(nonEmptyInputs); + return input.stream().map(TRIM).filter(NOT_EMPTY).collect(Collectors.toList()); } + private static final Function> COMMA_SPLITTER = + input -> Splitter.on(",").trimResults().omitEmptyStrings().splitToList(input).stream(); + /** * Split each element of an Iterable at commas. * @param input Iterable over strings. * @return An Iterable over string which breaks down each input element at comma boundaries */ @Nonnull - public static List splitAtCommasAndTrim(Iterable input) { - if(input==null) { + public static List splitAtCommasAndTrim(List input) { + if (input==null) { return Collections.emptyList(); } - Iterable nonEmptyInputs = Iterables.filter(input, Predicates.notNull()); - return Lists.newArrayList(Iterables.concat(Iterables.transform(nonEmptyInputs, COMMA_SPLITTER))); + return input.stream().filter(Objects::nonNull).flatMap(COMMA_SPLITTER).collect(Collectors.toList()); } public static String[] splitOnSpaceWithEscape(String toSplit) { @@ -175,7 +157,6 @@ public static String[] splitOnSpaceWithEscape(String toSplit) { return res; } - /** * Join a list of objects to a string with a given separator by calling Object.toString() on the elements. * @@ -383,20 +364,20 @@ public static String ensureRegistryHttpUrl(String registry) { return "https://" + registry; } - public static File prepareAbsoluteOutputDirPath(MojoParameters params, String dir, String path) { - return prepareAbsolutePath(params, new File(params.getOutputDirectory(), dir).toString(), path); + public static File prepareAbsoluteOutputDirPath(BuildContext ctx, String dir, String path) { + return prepareAbsolutePath(ctx, new File(ctx.getOutputDirectory(), dir).toString(), path); } - public static File prepareAbsoluteSourceDirPath(MojoParameters params, String path) { - return prepareAbsolutePath(params, params.getSourceDirectory(), path); + public static File prepareAbsoluteSourceDirPath(BuildContext ctx, String path) { + return prepareAbsolutePath(ctx, ctx.getSourceDirectory(), path); } - private static File prepareAbsolutePath(MojoParameters params, String directory, String path) { + private static File prepareAbsolutePath(BuildContext ctx, String directory, String path) { File file = new File(path); if (file.isAbsolute()) { return file; } - return new File(new File(params.getProject().getBasedir(), directory), path); + return new File(new File(ctx.getBasedir(), directory), path); } // create a timestamp file holding time in epoch seconds diff --git a/src/main/java/io/fabric8/maven/docker/util/MojoParameters.java b/src/main/java/io/fabric8/maven/docker/util/MojoParameters.java deleted file mode 100644 index 51bf6cc2d..000000000 --- a/src/main/java/io/fabric8/maven/docker/util/MojoParameters.java +++ /dev/null @@ -1,81 +0,0 @@ -package io.fabric8.maven.docker.util; - -import java.util.List; - -import org.apache.maven.archiver.MavenArchiveConfiguration; -import org.apache.maven.execution.MavenSession; -import org.apache.maven.project.MavenProject; -import org.apache.maven.settings.Settings; -import org.apache.maven.shared.filtering.MavenFileFilter; -import org.apache.maven.shared.filtering.MavenReaderFilter; - -/** - * Helper class for encapsulating Mojo params which are not Plexus components - * - * @author roland - * @since 09.05.14 - */ -public class MojoParameters { - private final MavenArchiveConfiguration archive; - private final MavenSession session; - private final MavenFileFilter mavenFileFilter; - private final MavenReaderFilter mavenFilterReader; - private final MavenProject project; - private final Settings settings; - - private final String outputDirectory; - private final String sourceDirectory; - - private final List reactorProjects; - - public MojoParameters(MavenSession session, MavenProject project, MavenArchiveConfiguration archive, MavenFileFilter mavenFileFilter, - MavenReaderFilter mavenFilterReader, Settings settings, String sourceDirectory, String outputDirectory, List reactorProjects) { - this.archive = archive; - this.session = session; - this.mavenFileFilter = mavenFileFilter; - this.mavenFilterReader = mavenFilterReader; - this.project = project; - this.settings = settings; - - this.sourceDirectory = sourceDirectory; - this.outputDirectory = outputDirectory; - - this.reactorProjects = reactorProjects; - } - - public MavenArchiveConfiguration getArchiveConfiguration() { - return archive; - } - - public String getSourceDirectory() { - return sourceDirectory; - } - - public String getOutputDirectory() { - return outputDirectory; - } - - public MavenSession getSession() { - return session; - } - - public MavenFileFilter getMavenFileFilter() { - return mavenFileFilter; - } - - public MavenReaderFilter getMavenFilterReader() { - return mavenFilterReader; - } - - public MavenProject getProject() { - return project; - } - - public Settings getSettings() { - return settings; - } - - public List getReactorProjects() { - return reactorProjects; - } -} diff --git a/src/test/java/io/fabric8/maven/docker/service/BuildServiceTest.java b/src/test/java/io/fabric8/maven/docker/build/DockerBuildServiceTest.java similarity index 73% rename from src/test/java/io/fabric8/maven/docker/service/BuildServiceTest.java rename to src/test/java/io/fabric8/maven/docker/build/DockerBuildServiceTest.java index aa6470ebd..99b7d6e76 100644 --- a/src/test/java/io/fabric8/maven/docker/service/BuildServiceTest.java +++ b/src/test/java/io/fabric8/maven/docker/build/DockerBuildServiceTest.java @@ -1,30 +1,33 @@ -package io.fabric8.maven.docker.service; +package io.fabric8.maven.docker.build; import java.io.File; +import java.io.IOException; import java.util.Collections; import io.fabric8.maven.docker.access.BuildOptions; import io.fabric8.maven.docker.access.DockerAccess; -import io.fabric8.maven.docker.assembly.DockerAssemblyManager; +import io.fabric8.maven.docker.build.maven.assembly.DockerAssemblyManager; +import io.fabric8.maven.docker.build.docker.DockerBuildService; +import io.fabric8.maven.docker.build.docker.DockerRegistryService; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import io.fabric8.maven.docker.config.BuildImageConfiguration; +import io.fabric8.maven.docker.build.maven.MavenArchiveService; +import io.fabric8.maven.docker.service.QueryService; import io.fabric8.maven.docker.util.Logger; -import io.fabric8.maven.docker.util.MojoParameters; import io.fabric8.maven.docker.access.DockerAccessException; import io.fabric8.maven.docker.config.ImageConfiguration; import mockit.*; import mockit.integration.junit4.JMockit; -import org.apache.maven.plugin.MojoExecutionException; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(JMockit.class) -public class BuildServiceTest { +public class DockerBuildServiceTest { private static final String NEW_IMAGE_ID = "efg789efg789"; private static final String OLD_IMAGE_ID = "abc123abc123"; @Tested - private BuildService buildService; + private DockerBuildService buildService; @Injectable private DockerAccess docker; @@ -40,30 +43,23 @@ public class BuildServiceTest { private String oldImageId; @Mocked - private MojoParameters params; + private MavenBuildContext buildContext; @Injectable private QueryService queryService; @Injectable - private ArchiveService archiveService; + private MavenArchiveService archiveService; @Injectable - private RegistryService registryService; + private DockerRegistryService registryService; - @Before - public void setup() throws Exception { - new Expectations() {{ - archiveService.createArchive(anyString, (BuildImageConfiguration) any, (MojoParameters) any, log); - result = new File("docker-build.tar"); - }}; - } @Test public void testBuildImageWithCleanup() throws Exception { givenAnImageConfiguration(true); givenImageIds(OLD_IMAGE_ID, NEW_IMAGE_ID); - whenBuildImage(true,false); + whenBuildImage(true); thenImageIsBuilt(); thenOldImageIsRemoved(); } @@ -72,7 +68,7 @@ public void testBuildImageWithCleanup() throws Exception { public void testBuildImageWithNoCleanup() throws Exception { givenAnImageConfiguration(false); givenImageIds(OLD_IMAGE_ID, NEW_IMAGE_ID); - whenBuildImage(false,false); + whenBuildImage(false); thenImageIsBuilt(); thenOldImageIsNotRemoved(); } @@ -81,7 +77,7 @@ public void testBuildImageWithNoCleanup() throws Exception { public void testCleanupCachedImage() throws Exception { givenAnImageConfiguration(true); givenImageIds(OLD_IMAGE_ID, OLD_IMAGE_ID); - whenBuildImage(false, false); + whenBuildImage(false); thenImageIsBuilt(); thenOldImageIsNotRemoved(); } @@ -90,7 +86,7 @@ public void testCleanupCachedImage() throws Exception { public void testCleanupNoExistingImage() throws Exception { givenAnImageConfiguration(true); givenImageIds(null, NEW_IMAGE_ID); - whenBuildImage(false, false); + whenBuildImage(false); thenImageIsBuilt(); thenOldImageIsNotRemoved(); } @@ -110,7 +106,7 @@ private void givenAnImageConfiguration(Boolean cleanup) { private void givenImageIds(final String oldImageId, final String newImageId) throws DockerAccessException { this.oldImageId = oldImageId; new Expectations() {{ - queryService.getImageId(imageConfig.getName()); result = new String[] { oldImageId, newImageId }; + docker.getImageId(imageConfig.getName()); result = new String[] { oldImageId, newImageId }; }}; } @@ -123,7 +119,7 @@ private void thenImageIsBuilt() throws DockerAccessException { }}; } - private void thenOldImageIsNotRemoved() throws DockerAccessException { + private void thenOldImageIsNotRemoved() { new FullVerifications(docker) {{ }}; @@ -135,9 +131,11 @@ private void thenOldImageIsRemoved() throws DockerAccessException { }}; } - private void whenBuildImage(boolean cleanup, boolean nocache) throws DockerAccessException, MojoExecutionException { + private void whenBuildImage(boolean cleanup) throws IOException { new Expectations() {{ docker.buildImage(withEqual(imageConfig.getName()), (File) any, (BuildOptions) any); + buildContext.createImageContentArchive(withEqual(imageConfig.getName()), (BuildImageConfiguration) any, withEqual(log)); + result = new File("docker-build.tar"); }}; if (cleanup) { new Expectations() {{ @@ -145,7 +143,7 @@ private void whenBuildImage(boolean cleanup, boolean nocache) throws DockerAcces }}; } - buildService.buildImage(imageConfig, params, nocache, Collections.emptyMap()); + buildService.buildImage(imageConfig, buildContext, Collections.emptyMap()); } } diff --git a/src/test/java/io/fabric8/maven/docker/service/RegistryServiceTest.java b/src/test/java/io/fabric8/maven/docker/build/DockerRegistryServiceTest.java similarity index 86% rename from src/test/java/io/fabric8/maven/docker/service/RegistryServiceTest.java rename to src/test/java/io/fabric8/maven/docker/build/DockerRegistryServiceTest.java index e97218004..228c368f6 100644 --- a/src/test/java/io/fabric8/maven/docker/service/RegistryServiceTest.java +++ b/src/test/java/io/fabric8/maven/docker/build/DockerRegistryServiceTest.java @@ -1,4 +1,4 @@ -package io.fabric8.maven.docker.service; +package io.fabric8.maven.docker.build; import java.util.HashMap; import java.util.Map; @@ -6,8 +6,11 @@ import io.fabric8.maven.docker.access.AuthConfig; import io.fabric8.maven.docker.access.DockerAccess; import io.fabric8.maven.docker.access.DockerAccessException; +import io.fabric8.maven.docker.build.docker.DockerRegistryService; +import io.fabric8.maven.docker.build.docker.ImagePullCache; +import io.fabric8.maven.docker.build.maven.MavenRegistryContext; import io.fabric8.maven.docker.config.ImagePullPolicy; -import io.fabric8.maven.docker.util.AuthConfigFactory; +import io.fabric8.maven.docker.build.maven.AuthConfigFactory; import io.fabric8.maven.docker.util.AutoPullMode; import io.fabric8.maven.docker.util.ImageName; import io.fabric8.maven.docker.util.Logger; @@ -24,15 +27,15 @@ * @author roland * @since 23.11.17 */ -public class RegistryServiceTest { +public class DockerRegistryServiceTest { private Exception actualException; private String imageName; private ImagePullPolicy imagePullPolicy; - private TestCacheStore cacheStore; + private TestBackend cacheStore; private AutoPullMode autoPullMode; - private RegistryService registryService; + private DockerRegistryService registryService; private boolean hasImage; private String registry; private Map authConfig; @@ -52,8 +55,8 @@ public void setup() { } private void reset() { - registryService = new RegistryService(docker, logger); - cacheStore = new TestCacheStore(); + cacheStore = new TestBackend(); + registryService = new DockerRegistryService(docker, logger, cacheStore); authConfig = new HashMap(); imageName = null; @@ -230,18 +233,12 @@ private void thenImageHasBeenPulledWithRegistry(final String registry) throws Do private void whenAutoPullImage() { try { - String iPolicyS = imagePullPolicy != null ? imagePullPolicy.toString() : null; - String autoPullModeS = autoPullMode != null ? autoPullMode.toString() : null; - ImagePullManager pullManager = new ImagePullManager(cacheStore,iPolicyS, autoPullModeS); - RegistryService.RegistryConfig.Builder registryConfigBuilder = - new RegistryService.RegistryConfig.Builder() - .authConfigFactory(authConfigFactory) - .authConfig(authConfig); - if (registry != null) { - registryConfigBuilder.registry(registry); - } - registryService.pullImageWithPolicy(imageName, pullManager, registryConfigBuilder.build(), hasImage); - + MavenRegistryContext buildContext = + new MavenRegistryContext.Builder() + .authConfigFactory(authConfigFactory) + .pullRegistry(registry) + .build(); + registryService.pullImage(imageName, imagePullPolicy, buildContext); } catch (Exception e) { //e.printStackTrace(); this.actualException = e; @@ -280,7 +277,7 @@ private void givenAnImage(String imageName) { this.imageName = imageName; } - private class TestCacheStore implements ImagePullManager.CacheStore { + private class TestBackend implements ImagePullCache.Backend { String cache; diff --git a/src/test/java/io/fabric8/maven/docker/assembly/DockerFileBuilderTest.java b/src/test/java/io/fabric8/maven/docker/build/docker/DockerFileBuilderTest.java similarity index 90% rename from src/test/java/io/fabric8/maven/docker/assembly/DockerFileBuilderTest.java rename to src/test/java/io/fabric8/maven/docker/build/docker/DockerFileBuilderTest.java index 625821f49..8f58d69a6 100644 --- a/src/test/java/io/fabric8/maven/docker/assembly/DockerFileBuilderTest.java +++ b/src/test/java/io/fabric8/maven/docker/build/docker/DockerFileBuilderTest.java @@ -1,9 +1,11 @@ -package io.fabric8.maven.docker.assembly; +package io.fabric8.maven.docker.build.docker; import java.io.IOException; import java.util.*; import java.util.regex.Pattern; +import io.fabric8.maven.docker.build.docker.DockerFileBuilder; +import io.fabric8.maven.docker.build.docker.DockerFileKeyword; import io.fabric8.maven.docker.config.*; import com.google.common.collect.ImmutableMap; import org.apache.commons.io.IOUtils; @@ -19,17 +21,17 @@ public class DockerFileBuilderTest { public void testBuildDockerFile() throws Exception { Arguments a = Arguments.Builder.get().withParam("c1").withParam("c2").build(); String dockerfileContent = new DockerFileBuilder().add("/src", "/dest") - .baseImage("image") - .cmd(a) - .env(ImmutableMap.of("foo", "bar")) - .basedir("/export") - .expose(Collections.singletonList("8080")) - .maintainer("maintainer@example.com") - .workdir("/tmp") - .labels(ImmutableMap.of("com.acme.foobar", "How are \"you\" ?")) - .volumes(Collections.singletonList("/vol1")) - .run(Arrays.asList("echo something", "echo second")) - .content(); + .baseImage("image") + .cmd(a) + .env(ImmutableMap.of("foo", "bar")) + .basedir("/export") + .expose(Collections.singletonList("8080")) + .maintainer("maintainer@example.com") + .workdir("/tmp") + .labels(ImmutableMap.of("com.acme.foobar", "How are \"you\" ?")) + .volumes(Collections.singletonList("/vol1")) + .run(Arrays.asList("echo something", "echo second")) + .content(); String expected = loadFile("docker/Dockerfile.test"); assertEquals(expected, stripCR(dockerfileContent)); } diff --git a/src/test/java/io/fabric8/maven/docker/util/AuthConfigFactoryTest.java b/src/test/java/io/fabric8/maven/docker/build/maven/AuthConfigFactoryTest.java similarity index 59% rename from src/test/java/io/fabric8/maven/docker/util/AuthConfigFactoryTest.java rename to src/test/java/io/fabric8/maven/docker/build/maven/AuthConfigFactoryTest.java index 1e100d24b..71e2f3b27 100644 --- a/src/test/java/io/fabric8/maven/docker/util/AuthConfigFactoryTest.java +++ b/src/test/java/io/fabric8/maven/docker/build/maven/AuthConfigFactoryTest.java @@ -1,8 +1,25 @@ -package io.fabric8.maven.docker.util; +package io.fabric8.maven.docker.build.maven; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import com.google.gson.Gson; import com.google.gson.JsonObject; - +import io.fabric8.maven.docker.access.AuthConfig; +import io.fabric8.maven.docker.build.maven.AuthConfigFactory; +import io.fabric8.maven.docker.util.JsonFactory; +import io.fabric8.maven.docker.util.Logger; +import mockit.Expectations; +import mockit.Mock; +import mockit.Mocked; +import mockit.integration.junit4.JMockit; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.settings.Server; import org.apache.maven.settings.Settings; @@ -19,22 +36,6 @@ import org.junit.runner.RunWith; import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.fabric8.maven.docker.access.AuthConfig; -import mockit.Expectations; -import mockit.Mock; -import mockit.Mocked; -import mockit.integration.junit4.JMockit; - import static java.util.Collections.singletonMap; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.hasProperty; @@ -85,29 +86,36 @@ public void containerSetup() throws ComponentLookupException { container.lookup(SecDispatcher.ROLE, "maven"); minTimes = 0; result = secDispatcher; }}; - factory = new AuthConfigFactory(container); - factory.setLog(log); gson = new Gson(); } + private void setupAuthConfigFactory(boolean skipExtendedAuth, Map authConfig) { + Map m = new HashMap(); + if (authConfig != null) { + m.putAll(authConfig); + } + if (skipExtendedAuth) { + m.put(AuthConfigFactory.SKIP_EXTENDED_AUTH, true); + } + factory = new AuthConfigFactory(container, settings, m, null, log); + } + @Test public void testEmpty() throws Exception { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - assertNull(factory.createAuthConfig(isPush,false,null,settings,null,"blubberbla:1611")); - } - }); + setupAuthConfigFactory(false, null); + executeWithTempHomeDir(homeDir -> assertNull(factory.createAuthConfig(isPush, null, "blubberbla:1611"))); } + @Test public void testSystemProperty() throws Exception { + setupAuthConfigFactory(false, null); System.setProperty("docker.push.username","roland"); System.setProperty("docker.push.password", "secret"); System.setProperty("docker.push.email", "roland@jolokia.org"); try { - AuthConfig config = factory.createAuthConfig(true, false, null, settings, null, null); + AuthConfig config = factory.createAuthConfig(true, null, null); verifyAuthConfig(config,"roland","secret","roland@jolokia.org"); } finally { System.clearProperty("docker.push.username"); @@ -119,96 +127,89 @@ public void testSystemProperty() throws Exception { @Test public void testDockerAuthLogin() throws Exception { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - checkDockerAuthLogin(homeDir,AuthConfigFactory.DOCKER_LOGIN_DEFAULT_REGISTRY,null); - checkDockerAuthLogin(homeDir,"localhost:5000","localhost:5000"); - checkDockerAuthLogin(homeDir,"https://localhost:5000","localhost:5000"); - } + setupAuthConfigFactory(false, null); + + executeWithTempHomeDir(homeDir -> { + checkDockerAuthLogin(homeDir, AuthConfigFactory.DOCKER_LOGIN_DEFAULT_REGISTRY, null); + checkDockerAuthLogin(homeDir,"localhost:5000","localhost:5000"); + checkDockerAuthLogin(homeDir,"https://localhost:5000","localhost:5000"); }); } @Test public void testDockerLoginNoConfig() throws MojoExecutionException, IOException { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File dir) throws IOException, MojoExecutionException { - AuthConfig config = factory.createAuthConfig(isPush, false, null, settings, "roland", null); - assertNull(config); - } + setupAuthConfigFactory(false, null); + + executeWithTempHomeDir(dir -> { + AuthConfig config = factory.createAuthConfig(isPush, "roland", null); + assertNull(config); }); } @Test public void testDockerLoginFallsBackToAuthWhenCredentialHelperDoesNotMatchDomain() throws MojoExecutionException, IOException { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - writeDockerConfigJson(createDockerConfig(homeDir),null,singletonMap("registry1", "credHelper1-does-not-exist")); - AuthConfig config = factory.createAuthConfig(isPush,false,null,settings,"roland","localhost:5000"); - verifyAuthConfig(config,"roland","secret","roland@jolokia.org"); - } + setupAuthConfigFactory(false, null); + + executeWithTempHomeDir(homeDir -> { + writeDockerConfigJson(createDockerConfig(homeDir),null,singletonMap("registry1", "credHelper1-does-not-exist")); + AuthConfig config = factory.createAuthConfig(isPush,"roland","localhost:5000"); + verifyAuthConfig(config,"roland","secret","roland@jolokia.org"); }); } @Test public void testDockerLoginNoAuthConfigFoundWhenCredentialHelperDoesNotMatchDomainOrAuth() throws MojoExecutionException, IOException { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - writeDockerConfigJson(createDockerConfig(homeDir),null,singletonMap("registry1", "credHelper1-does-not-exist")); - AuthConfig config = factory.createAuthConfig(isPush,false,null,settings,"roland","does-not-exist-either:5000"); - assertNull(config); - } + setupAuthConfigFactory(false, null); + + executeWithTempHomeDir(homeDir -> { + writeDockerConfigJson(createDockerConfig(homeDir),null,singletonMap("registry1", "credHelper1-does-not-exist")); + AuthConfig config = factory.createAuthConfig(isPush,"roland","does-not-exist-either:5000"); + assertNull(config); }); } @Test public void testDockerLoginSelectCredentialHelper() throws MojoExecutionException, IOException { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - writeDockerConfigJson(createDockerConfig(homeDir),"credsStore-does-not-exist",singletonMap("registry1", "credHelper1-does-not-exist")); - expectedException.expect(MojoExecutionException.class); - expectedException.expectCause(Matchers.allOf( - instanceOf(IOException.class), - hasProperty("message",startsWith("Failed to start 'docker-credential-credHelper1-does-not-exist version'")) - )); - factory.createAuthConfig(isPush,false,null,settings,"roland","registry1"); - } + setupAuthConfigFactory(false, null); + + executeWithTempHomeDir(homeDir -> { + writeDockerConfigJson(createDockerConfig(homeDir),"credsStore-does-not-exist",singletonMap("registry1", "credHelper1-does-not-exist")); + expectedException.expect(RuntimeException.class); + expectedException.expectCause(Matchers.allOf( + instanceOf(IOException.class), + hasProperty("message",startsWith("Failed to start 'docker-credential-credHelper1-does-not-exist version'")) + )); + factory.createAuthConfig(isPush,"roland","registry1"); }); } @Test public void testDockerLoginSelectCredentialsStore() throws MojoExecutionException, IOException { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - writeDockerConfigJson(createDockerConfig(homeDir),"credsStore-does-not-exist",singletonMap("registry1", "credHelper1-does-not-exist")); - expectedException.expect(MojoExecutionException.class); - expectedException.expectCause(Matchers.allOf( - instanceOf(IOException.class), - hasProperty("message",startsWith("Failed to start 'docker-credential-credsStore-does-not-exist version'")) - )); - factory.createAuthConfig(isPush,false,null,settings,"roland",null); - } + setupAuthConfigFactory(false, null); + + executeWithTempHomeDir(homeDir -> { + writeDockerConfigJson(createDockerConfig(homeDir),"credsStore-does-not-exist",singletonMap("registry1", "credHelper1-does-not-exist")); + expectedException.expect(RuntimeException.class); + expectedException.expectCause(Matchers.allOf( + instanceOf(IOException.class), + hasProperty("message",startsWith("Failed to start 'docker-credential-credsStore-does-not-exist version'")) + )); + factory.createAuthConfig(isPush,"roland",null); }); } @Test public void testDockerLoginDefaultToCredentialsStore() throws MojoExecutionException, IOException { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - writeDockerConfigJson(createDockerConfig(homeDir),"credsStore-does-not-exist",singletonMap("registry1", "credHelper1-does-not-exist")); - expectedException.expect(MojoExecutionException.class); - expectedException.expectCause(Matchers.allOf( - instanceOf(IOException.class), - hasProperty("message",startsWith("Failed to start 'docker-credential-credsStore-does-not-exist version'")) - )); - factory.createAuthConfig(isPush,false,null,settings,"roland","registry2"); - } + setupAuthConfigFactory(false, null); + + executeWithTempHomeDir(homeDir -> { + writeDockerConfigJson(createDockerConfig(homeDir),"credsStore-does-not-exist",singletonMap("registry1", "credHelper1-does-not-exist")); + expectedException.expect(RuntimeException.class); + expectedException.expectCause(Matchers.allOf( + instanceOf(IOException.class), + hasProperty("message",startsWith("Failed to start 'docker-credential-credsStore-does-not-exist version'")) + )); + factory.createAuthConfig(isPush,"roland","registry2"); }); } @@ -229,14 +230,15 @@ interface HomeDirExecutor { } private void checkDockerAuthLogin(File homeDir,String configRegistry,String lookupRegistry) - throws IOException, MojoExecutionException { + throws IOException { + setupAuthConfigFactory(false, null); + writeDockerConfigJson(createDockerConfig(homeDir), "roland", "secret", "roland@jolokia.org", configRegistry); - AuthConfig config = factory.createAuthConfig(isPush, false, null, settings, "roland", lookupRegistry); + AuthConfig config = factory.createAuthConfig(isPush, "roland", lookupRegistry); verifyAuthConfig(config,"roland","secret","roland@jolokia.org"); } - private File createDockerConfig(File homeDir) - throws IOException { + private File createDockerConfig(File homeDir) { File dockerDir = new File(homeDir,".docker"); dockerDir.mkdirs(); return dockerDir; @@ -284,29 +286,27 @@ private void addAuths(JsonObject config,String user,String password,String email @Test public void testOpenShiftConfigFromPluginConfig() throws Exception { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - createOpenShiftConfig(homeDir,"openshift_simple_config.yaml"); - Map authConfigMap = new HashMap<>(); - authConfigMap.put("useOpenShiftAuth","true"); - AuthConfig config = factory.createAuthConfig(isPush, false, authConfigMap, settings, "roland", null); - verifyAuthConfig(config,"admin","token123",null); - } + Map authConfigMap = new HashMap<>(); + authConfigMap.put("useOpenShiftAuth","true"); + setupAuthConfigFactory(false, authConfigMap); + + executeWithTempHomeDir(homeDir -> { + createOpenShiftConfig(homeDir,"openshift_simple_config.yaml"); + AuthConfig config = factory.createAuthConfig(isPush, "roland", null); + verifyAuthConfig(config,"admin","token123",null); }); } @Test public void testOpenShiftConfigFromSystemProps() throws Exception { + setupAuthConfigFactory(false, null); + try { System.setProperty("docker.useOpenShiftAuth","true"); - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - createOpenShiftConfig(homeDir, "openshift_simple_config.yaml"); - AuthConfig config = factory.createAuthConfig(isPush, false, null, settings, "roland", null); - verifyAuthConfig(config, "admin", "token123", null); - } + executeWithTempHomeDir(homeDir -> { + createOpenShiftConfig(homeDir, "openshift_simple_config.yaml"); + AuthConfig config = factory.createAuthConfig(isPush, "roland", null); + verifyAuthConfig(config, "admin", "token123", null); }); } finally { System.getProperties().remove("docker.useOpenShiftAuth"); @@ -315,17 +315,16 @@ public void exec(File homeDir) throws IOException, MojoExecutionException { @Test public void testOpenShiftConfigFromSystemPropsNegative() throws Exception { + Map authConfigMap = new HashMap<>(); + authConfigMap.put("useOpenShiftAuth","true"); + setupAuthConfigFactory(false, authConfigMap); + try { System.setProperty("docker.useOpenShiftAuth","false"); - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - createOpenShiftConfig(homeDir, "openshift_simple_config.yaml"); - Map authConfigMap = new HashMap<>(); - authConfigMap.put("useOpenShiftAuth","true"); - AuthConfig config = factory.createAuthConfig(isPush, false, authConfigMap, settings, "roland", null); - assertNull(config); - } + executeWithTempHomeDir(homeDir -> { + createOpenShiftConfig(homeDir, "openshift_simple_config.yaml"); + AuthConfig config = factory.createAuthConfig(isPush, "roland", null); + assertNull(config); }); } finally { System.getProperties().remove("docker.useOpenShiftAuth"); @@ -334,16 +333,15 @@ public void exec(File homeDir) throws IOException, MojoExecutionException { @Test public void testOpenShiftConfigNotLoggedIn() throws Exception { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - createOpenShiftConfig(homeDir,"openshift_nologin_config.yaml"); - Map authConfigMap = new HashMap<>(); - authConfigMap.put("useOpenShiftAuth","true"); - expectedException.expect(MojoExecutionException.class); - expectedException.expectMessage(containsString("~/.kube/config")); - factory.createAuthConfig(isPush,false,authConfigMap,settings,"roland",null); - } + Map authConfigMap = new HashMap<>(); + authConfigMap.put("useOpenShiftAuth","true"); + setupAuthConfigFactory(false, authConfigMap); + + executeWithTempHomeDir(homeDir -> { + createOpenShiftConfig(homeDir,"openshift_nologin_config.yaml"); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage(containsString("~/.kube/config")); + factory.createAuthConfig(isPush,"roland",null); }); } @@ -356,16 +354,18 @@ private void createOpenShiftConfig(File homeDir,String testConfig) throws IOExce } @Test - public void testSystemPropertyNoPassword() throws Exception { - expectedException.expect(MojoExecutionException.class); + public void testSystemPropertyNoPassword() { + expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("No docker.password provided for username secret"); checkException("docker.username"); } - private void checkException(String key) throws MojoExecutionException { + private void checkException(String key) { + setupAuthConfigFactory(false, null); + System.setProperty(key, "secret"); try { - factory.createAuthConfig(isPush, false, null, settings, null, null); + factory.createAuthConfig(isPush, null, null); } finally { System.clearProperty(key); } @@ -373,12 +373,15 @@ private void checkException(String key) throws MojoExecutionException { @Test public void testFromPluginConfiguration() throws MojoExecutionException { + Map pluginConfig = new HashMap(); pluginConfig.put("username", "roland"); pluginConfig.put("password", "secret"); pluginConfig.put("email", "roland@jolokia.org"); - AuthConfig config = factory.createAuthConfig(isPush, false, pluginConfig, settings, null, null); + setupAuthConfigFactory(false, pluginConfig); + + AuthConfig config = factory.createAuthConfig(isPush, null, null); verifyAuthConfig(config, "roland", "secret", "roland@jolokia.org"); } @@ -390,7 +393,9 @@ public void testFromPluginConfigurationPull() throws MojoExecutionException { pullConfig.put("email", "roland@jolokia.org"); Map pluginConfig = new HashMap(); pluginConfig.put("pull",pullConfig); - AuthConfig config = factory.createAuthConfig(false, false, pluginConfig, settings, null, null); + setupAuthConfigFactory(false, pluginConfig); + + AuthConfig config = factory.createAuthConfig(false, null, null); verifyAuthConfig(config, "roland", "secret", "roland@jolokia.org"); } @@ -399,15 +404,19 @@ public void testFromPluginConfigurationPull() throws MojoExecutionException { public void testFromPluginConfigurationFailed() throws MojoExecutionException { Map pluginConfig = new HashMap(); pluginConfig.put("username","admin"); - expectedException.expect(MojoExecutionException.class); + setupAuthConfigFactory(false, pluginConfig); + + expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("No 'password' given while using in configuration for mode DEFAULT"); - factory.createAuthConfig(isPush,false,pluginConfig,settings,null,null); + factory.createAuthConfig(isPush,null,null); } @Test public void testFromSettingsSimple() throws MojoExecutionException { setupServers(); - AuthConfig config = factory.createAuthConfig(isPush, false, null, settings, "roland", "test.org"); + setupAuthConfigFactory(false, null); + + AuthConfig config = factory.createAuthConfig(isPush, "roland", "test.org"); assertNotNull(config); verifyAuthConfig(config, "roland", "secret", "roland@jolokia.org"); } @@ -415,7 +424,9 @@ public void testFromSettingsSimple() throws MojoExecutionException { @Test public void testFromSettingsDefault() throws MojoExecutionException { setupServers(); - AuthConfig config = factory.createAuthConfig(isPush, false, null, settings, "fabric8io", "test.org"); + setupAuthConfigFactory(false, null); + + AuthConfig config = factory.createAuthConfig(isPush, "fabric8io", "test.org"); assertNotNull(config); verifyAuthConfig(config, "fabric8io", "secret2", "fabric8io@redhat.com"); } @@ -423,19 +434,20 @@ public void testFromSettingsDefault() throws MojoExecutionException { @Test public void testFromSettingsDefault2() throws MojoExecutionException { setupServers(); - AuthConfig config = factory.createAuthConfig(isPush, false, null, settings, "tanja", null); + setupAuthConfigFactory(false, null); + + AuthConfig config = factory.createAuthConfig(isPush, "tanja", null); assertNotNull(config); verifyAuthConfig(config,"tanja","doublesecret","tanja@jolokia.org"); } @Test public void testWrongUserName() throws IOException, MojoExecutionException { - executeWithTempHomeDir(new HomeDirExecutor() { - @Override - public void exec(File homeDir) throws IOException, MojoExecutionException { - setupServers(); - assertNull(factory.createAuthConfig(isPush,false,null,settings,"roland","another.repo.org")); - } + setupAuthConfigFactory(false, null); + + executeWithTempHomeDir(homeDir -> { + setupServers(); + assertNull(factory.createAuthConfig(isPush,"roland","another.repo.org")); }); } diff --git a/src/test/java/io/fabric8/maven/docker/assembly/DockerAssemblyConfigurationSourceTest.java b/src/test/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyConfigurationSourceTest.java similarity index 71% rename from src/test/java/io/fabric8/maven/docker/assembly/DockerAssemblyConfigurationSourceTest.java rename to src/test/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyConfigurationSourceTest.java index 6593d1509..32e210dae 100644 --- a/src/test/java/io/fabric8/maven/docker/assembly/DockerAssemblyConfigurationSourceTest.java +++ b/src/test/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyConfigurationSourceTest.java @@ -1,20 +1,22 @@ -package io.fabric8.maven.docker.assembly; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +package io.fabric8.maven.docker.build.maven.assembly; import java.io.File; import java.util.Arrays; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; +import io.fabric8.maven.docker.build.maven.assembly.BuildDirs; +import io.fabric8.maven.docker.build.maven.assembly.DockerAssemblyConfigurationSource; import io.fabric8.maven.docker.config.AssemblyConfiguration; import io.fabric8.maven.docker.util.EnvUtil; -import io.fabric8.maven.docker.util.MojoParameters; import org.apache.maven.project.MavenProject; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + public class DockerAssemblyConfigurationSourceTest { private AssemblyConfiguration assemblyConfig; @@ -44,42 +46,47 @@ public void permissionMode() { @Test public void testCreateSourceAbsolute() { - testCreateSource(buildParameters(".", "/src/docker".replace("/", File.separator), "/output/docker".replace("/", File.separator))); + testCreateSource(buildBuildContetxt(".", "/src/docker".replace("/", File.separator), "/output/docker".replace("/", File.separator))); } @Test public void testCreateSourceRelative() { - testCreateSource(buildParameters(".","src/docker".replace("/", File.separator), "output/docker".replace("/", File.separator))); + testCreateSource(buildBuildContetxt(".","src/docker".replace("/", File.separator), "output/docker".replace("/", File.separator))); } @Test public void testOutputDirHasImage() { String image = "image"; - MojoParameters params = buildParameters(".", "src/docker", "output/docker"); - DockerAssemblyConfigurationSource source = new DockerAssemblyConfigurationSource(params, - new BuildDirs(image, params),assemblyConfig); + MavenBuildContext context = buildBuildContetxt(".", "src/docker", "output/docker"); + DockerAssemblyConfigurationSource source = new DockerAssemblyConfigurationSource(context, + new BuildDirs(image, context), assemblyConfig); assertTrue(containsDir(image, source.getOutputDirectory())); assertTrue(containsDir(image, source.getWorkingDirectory())); assertTrue(containsDir(image, source.getTemporaryRootDirectory())); } - private MojoParameters buildParameters(String projectDir, String sourceDir, String outputDir) { + private MavenBuildContext buildBuildContetxt(String projectDir, String sourceDir, String outputDir) { MavenProject mavenProject = new MavenProject(); mavenProject.setFile(new File(projectDir)); - return new MojoParameters(null, mavenProject, null, null, null, null, sourceDir, outputDir, null); + return new MavenBuildContext.Builder() + .project(mavenProject) + .sourceDirectory(sourceDir) + .outputDirectory(outputDir) + .build(); } @Test public void testEmptyAssemblyConfig() { - DockerAssemblyConfigurationSource source = new DockerAssemblyConfigurationSource( - new MojoParameters(null, null, null, null, null, null, "/src/docker", "/output/docker", null), - null,null - ); + MavenBuildContext buildContext = new MavenBuildContext.Builder() + .sourceDirectory("/src/docker") + .outputDirectory("/output/docker") + .build(); + DockerAssemblyConfigurationSource source = new DockerAssemblyConfigurationSource(buildContext,null,null); assertEquals(0,source.getDescriptors().length); } - private void testCreateSource(MojoParameters params) { + private void testCreateSource(MavenBuildContext params) { DockerAssemblyConfigurationSource source = new DockerAssemblyConfigurationSource(params, new BuildDirs("image", params), assemblyConfig); @@ -119,10 +126,12 @@ public void testReactorProjects() { MavenProject reactorProject2 = new MavenProject(); reactorProject2.setFile(new File("../reactor-2")); - DockerAssemblyConfigurationSource source = new DockerAssemblyConfigurationSource( - new MojoParameters(null, null, null, null, null, null, "/src/docker", "/output/docker", Arrays.asList(new MavenProject[] { reactorProject1, reactorProject2 })), - null,null - ); + MavenBuildContext buildContext = new MavenBuildContext.Builder() + .sourceDirectory("/src/docker") + .outputDirectory("/output/docker") + .reactorProjects(Arrays.asList(reactorProject1, reactorProject2)) + .build(); + DockerAssemblyConfigurationSource source = new DockerAssemblyConfigurationSource(buildContext,null,null); assertEquals(2,source.getReactorProjects().size()); } } diff --git a/src/test/java/io/fabric8/maven/docker/assembly/DockerAssemblyManagerTest.java b/src/test/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyManagerTest.java similarity index 82% rename from src/test/java/io/fabric8/maven/docker/assembly/DockerAssemblyManagerTest.java rename to src/test/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyManagerTest.java index 848a740a9..8d04e24af 100644 --- a/src/test/java/io/fabric8/maven/docker/assembly/DockerAssemblyManagerTest.java +++ b/src/test/java/io/fabric8/maven/docker/build/maven/assembly/DockerAssemblyManagerTest.java @@ -1,27 +1,28 @@ -package io.fabric8.maven.docker.assembly; +package io.fabric8.maven.docker.build.maven.assembly; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.function.Function; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; +import io.fabric8.maven.docker.build.docker.DockerFileBuilder; import io.fabric8.maven.docker.config.AssemblyConfiguration; import io.fabric8.maven.docker.config.BuildImageConfiguration; import io.fabric8.maven.docker.util.AnsiLogger; import io.fabric8.maven.docker.util.DockerFileUtil; import io.fabric8.maven.docker.util.Logger; -import io.fabric8.maven.docker.util.MojoParameters; import mockit.Expectations; import mockit.Injectable; import mockit.Mock; -import mockit.MockUp; import mockit.Tested; import mockit.Verifications; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.MavenArtifactRepository; import org.apache.maven.execution.MavenSession; -import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.SystemStreamLog; import org.apache.maven.plugins.assembly.AssemblerConfigurationSource; import org.apache.maven.plugins.assembly.InvalidAssemblerConfigurationException; import org.apache.maven.plugins.assembly.archive.ArchiveCreationException; @@ -30,11 +31,9 @@ import org.apache.maven.plugins.assembly.io.AssemblyReadException; import org.apache.maven.plugins.assembly.io.AssemblyReader; import org.apache.maven.plugins.assembly.model.Assembly; -import org.apache.maven.plugin.logging.SystemStreamLog; import org.apache.maven.project.MavenProject; import org.apache.maven.settings.Settings; import org.codehaus.plexus.archiver.manager.ArchiverManager; -import org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator; import org.codehaus.plexus.util.ReflectionUtils; import org.junit.Test; @@ -70,19 +69,18 @@ public void testNoAssembly() { } @Test - public void assemblyFiles(@Injectable final MojoParameters mojoParams, + public void assemblyFiles(@Injectable final MavenBuildContext mavenBuildContext, @Injectable final MavenProject project, - @Injectable final Assembly assembly) throws AssemblyFormattingException, ArchiveCreationException, InvalidAssemblerConfigurationException, MojoExecutionException, AssemblyReadException, IllegalAccessException { + @Injectable final Assembly assembly) throws AssemblyFormattingException, ArchiveCreationException, InvalidAssemblerConfigurationException, AssemblyReadException, IllegalAccessException, IOException { ReflectionUtils.setVariableValueInObject(assemblyManager, "trackArchiver", trackArchiver); new Expectations() {{ - mojoParams.getOutputDirectory(); + mavenBuildContext.getOutputDirectory(); result = "target/"; times = 3; - mojoParams.getProject(); - project.getBasedir(); - result = "."; + mavenBuildContext.getBasedir(); + result = new File("."); assemblyReader.readAssemblies((AssemblerConfigurationSource) any); result = Arrays.asList(assembly); @@ -91,7 +89,7 @@ public void assemblyFiles(@Injectable final MojoParameters mojoParams, BuildImageConfiguration buildConfig = createBuildConfig(); - assemblyManager.getAssemblyFiles("testImage", buildConfig, mojoParams, new AnsiLogger(new SystemStreamLog(),true,true)); + assemblyManager.getAssemblyFiles("testImage", buildConfig, mavenBuildContext, new AnsiLogger(new SystemStreamLog(),true,true)); } @Test @@ -149,15 +147,15 @@ private BuildImageConfiguration createBuildConfig() { .build(); } - private FixedStringSearchInterpolator createInterpolator(BuildImageConfiguration buildConfig) { + private Function createInterpolator(BuildImageConfiguration buildConfig) { MavenProject project = new MavenProject(); project.setArtifactId("docker-maven-plugin"); - return DockerFileUtil.createInterpolator(mockMojoParams(project), buildConfig.getFilter()); + return s -> DockerFileUtil.createInterpolator(mockMavenBuildContext(project), buildConfig.getFilter()).interpolate(s); } - private MojoParameters mockMojoParams(MavenProject project) { + private MavenBuildContext mockMavenBuildContext(MavenProject project) { Settings settings = new Settings(); ArtifactRepository localRepository = new MavenArtifactRepository() { @Mock @@ -167,7 +165,15 @@ public String getBasedir() { }; @SuppressWarnings("deprecation") MavenSession session = new MavenSession(null, settings, localRepository, null, null, Collections.emptyList(), ".", null, null, new Date()); - return new MojoParameters(session, project, null, null, null, settings, "src", "target", Collections.singletonList(project)); + + return new MavenBuildContext.Builder() + .project(project) + .session(session) + .settings(settings) + .sourceDirectory("src") + .outputDirectory("target") + .reactorProjects(Collections.singletonList(project)) + .build(); } } diff --git a/src/test/java/io/fabric8/maven/docker/assembly/MappingTrackArchiverTest.java b/src/test/java/io/fabric8/maven/docker/build/maven/assembly/MappingTrackArchiverTest.java similarity index 93% rename from src/test/java/io/fabric8/maven/docker/assembly/MappingTrackArchiverTest.java rename to src/test/java/io/fabric8/maven/docker/build/maven/assembly/MappingTrackArchiverTest.java index 74b725a55..515f30731 100644 --- a/src/test/java/io/fabric8/maven/docker/assembly/MappingTrackArchiverTest.java +++ b/src/test/java/io/fabric8/maven/docker/build/maven/assembly/MappingTrackArchiverTest.java @@ -1,4 +1,4 @@ -package io.fabric8.maven.docker.assembly;/* +package io.fabric8.maven.docker.build.maven.assembly;/* * * Copyright 2014 Roland Huss * @@ -18,6 +18,8 @@ import java.io.File; import java.util.List; +import io.fabric8.maven.docker.build.maven.assembly.AssemblyFiles; +import io.fabric8.maven.docker.build.maven.assembly.MappingTrackArchiver; import mockit.Injectable; import org.apache.commons.io.FileUtils; import org.apache.maven.execution.MavenSession; diff --git a/src/test/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandlerTest.java b/src/test/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandlerTest.java index 531ed4ea1..705f529b7 100644 --- a/src/test/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandlerTest.java +++ b/src/test/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandlerTest.java @@ -18,9 +18,13 @@ import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; -import io.fabric8.maven.docker.config.*; import io.fabric8.maven.docker.config.Arguments; import io.fabric8.maven.docker.config.AssemblyConfiguration; import io.fabric8.maven.docker.config.BuildImageConfiguration; @@ -41,16 +45,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import static io.fabric8.maven.docker.config.BuildImageConfiguration.DEFAULT_CLEANUP; -import static io.fabric8.maven.docker.config.BuildImageConfiguration.DEFAULT_FILTER; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -626,7 +620,7 @@ public void testNoCleanup() throws Exception { String[] testData = new String[] {k(ConfigKey.NAME), "image", k(ConfigKey.CLEANUP), "none", k(ConfigKey.FROM), "base" }; ImageConfiguration config = resolveExternalImageConfig(testData); - assertEquals(CleanupMode.NONE, config.getBuildConfiguration().cleanupMode()); + assertEquals(CleanupMode.NONE, CleanupMode.parse(config.getBuildConfiguration().getCleanupMode())); } @Test @@ -707,7 +701,7 @@ public void testFilterDefault() { String[] testData = new String[] {k(ConfigKey.NAME), "image", k(ConfigKey.FROM), "base" }; ImageConfiguration config = resolveExternalImageConfig(testData); - assertEquals(DEFAULT_FILTER, config.getBuildConfiguration().getFilter()); + assertNull(config.getBuildConfiguration().getFilter()); } @Test @@ -724,7 +718,7 @@ public void testCleanupDefault() { String[] testData = new String[] {k(ConfigKey.NAME), "image", k(ConfigKey.FROM), "base" }; ImageConfiguration config = resolveExternalImageConfig(testData); - assertEquals(DEFAULT_CLEANUP, config.getBuildConfiguration().cleanupMode().toParameter()); + assertEquals(null, config.getBuildConfiguration().getCleanupMode()); } @Test @@ -733,7 +727,7 @@ public void testCleanup() { String[] testData = new String[] {k(ConfigKey.NAME), "image", k(ConfigKey.FROM), "base", k(ConfigKey.CLEANUP), mode.toParameter() }; ImageConfiguration config = resolveExternalImageConfig(testData); - assertEquals(mode, config.getBuildConfiguration().cleanupMode()); + assertEquals(mode, CleanupMode.parse(config.getBuildConfiguration().getCleanupMode())); } @@ -859,7 +853,7 @@ private ImageConfiguration resolveExternalImageConfig(String[] testData) { } private void validateBuildConfiguration(BuildImageConfiguration buildConfig) { - assertEquals(CleanupMode.TRY_TO_REMOVE, buildConfig.cleanupMode()); + assertEquals(CleanupMode.TRY_TO_REMOVE, CleanupMode.parse(buildConfig.getCleanupMode())); assertEquals("command.sh", buildConfig.getCmd().getShell()); assertEquals("image", buildConfig.getFrom()); assertEquals("image-ext", buildConfig.getFromExt().get("name")); diff --git a/src/test/java/io/fabric8/maven/docker/service/LoadImageTest.java b/src/test/java/io/fabric8/maven/docker/service/LoadImageTest.java index 3bf9555a7..83fb38321 100644 --- a/src/test/java/io/fabric8/maven/docker/service/LoadImageTest.java +++ b/src/test/java/io/fabric8/maven/docker/service/LoadImageTest.java @@ -1,17 +1,20 @@ package io.fabric8.maven.docker.service; import java.io.File; +import java.io.IOException; import java.util.Collections; import io.fabric8.maven.docker.access.DockerAccess; import io.fabric8.maven.docker.access.DockerAccessException; +import io.fabric8.maven.docker.build.docker.DockerBuildService; +import io.fabric8.maven.docker.build.docker.DockerRegistryService; +import io.fabric8.maven.docker.build.maven.MavenArchiveService; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import io.fabric8.maven.docker.config.BuildImageConfiguration; import io.fabric8.maven.docker.config.ConfigHelper; import io.fabric8.maven.docker.config.ImageConfiguration; import io.fabric8.maven.docker.util.Logger; -import io.fabric8.maven.docker.util.MojoParameters; -import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.junit.Test; import org.junit.runner.RunWith; @@ -26,7 +29,7 @@ @RunWith(JMockit.class) public class LoadImageTest { @Tested - private BuildService buildService; + private DockerBuildService buildService; @Injectable private DockerAccess docker; @@ -40,33 +43,32 @@ public class LoadImageTest { private MavenProject project; @Mocked - private MojoParameters params; + private MavenBuildContext buildContext; @Injectable private QueryService queryService; @Injectable - private ArchiveService archiveService; + private MavenArchiveService archiveService; @Injectable - private RegistryService registryService; + private DockerRegistryService registryService; private String dockerArchive; @Test - public void testLoadImage() throws DockerAccessException, MojoExecutionException { - givenMojoParameters(); + public void testLoadImage() throws IOException { + givenBuildContext(); givenAnImageConfiguration(); givenDockerArchive("test.tar"); whenBuildImage(); thenImageIsBuilt(); } - private void givenMojoParameters() { + private void givenBuildContext() { new Expectations() {{ - params.getProject(); - project.getBasedir(); result = "/maven-project"; - params.getSourceDirectory(); result = "src/main/docker"; + buildContext.getBasedir(); result = "/maven-project"; + buildContext.getSourceDirectory();result = "src/main/docker"; }}; } @@ -87,8 +89,8 @@ private void givenAnImageConfiguration() { imageConfig.initAndValidate(ConfigHelper.NameFormatter.IDENTITY,log); } - private void whenBuildImage() throws DockerAccessException, MojoExecutionException { - buildService.buildImage(imageConfig, params, false, Collections.emptyMap()); + private void whenBuildImage() throws IOException { + buildService.buildImage(imageConfig, buildContext, Collections.emptyMap()); } private void thenImageIsBuilt() throws DockerAccessException { diff --git a/src/test/java/io/fabric8/maven/docker/util/DockerFileUtilTest.java b/src/test/java/io/fabric8/maven/docker/util/DockerFileUtilTest.java index ff245c641..7ba067bee 100644 --- a/src/test/java/io/fabric8/maven/docker/util/DockerFileUtilTest.java +++ b/src/test/java/io/fabric8/maven/docker/util/DockerFileUtilTest.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Properties; +import io.fabric8.maven.docker.build.maven.MavenBuildContext; import org.apache.commons.io.FileUtils; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.MavenArtifactRepository; @@ -33,9 +34,6 @@ import org.codehaus.plexus.util.IOUtil; import org.junit.Test; -import mockit.Mock; -import mockit.MockUp; - import static io.fabric8.maven.docker.util.PathTestUtil.createTmpFile; import static org.junit.Assert.assertEquals; @@ -49,7 +47,7 @@ public class DockerFileUtilTest { public void testSimple() throws Exception { File toTest = copyToTempDir("Dockerfile_from_simple"); assertEquals("fabric8/s2i-java", DockerFileUtil.extractBaseImage( - toTest, FixedStringSearchInterpolator.create())); + toTest, s -> FixedStringSearchInterpolator.create().interpolate(s))); } private File copyToTempDir(String resource) throws IOException { @@ -63,7 +61,8 @@ private File copyToTempDir(String resource) throws IOException { @Test public void interpolate() throws Exception { - MojoParameters params = mockMojoParams(); + MavenBuildContext buildContext = mockMavenBuildContext(); + Map filterMapping = new HashMap<>(); filterMapping.put("none", "false"); filterMapping.put("var", "${*}"); @@ -74,7 +73,7 @@ public void interpolate() throws Exception { File dockerFile = getDockerfilePath(i, entry.getKey()); File expectedDockerFile = new File(dockerFile.getParent(), dockerFile.getName() + ".expected"); File actualDockerFile = createTmpFile(dockerFile.getName()); - FixedStringSearchInterpolator interpolator = DockerFileUtil.createInterpolator(params, entry.getValue()); + FixedStringSearchInterpolator interpolator = DockerFileUtil.createInterpolator(buildContext, entry.getValue()); FileUtils.write(actualDockerFile, DockerFileUtil.interpolate(dockerFile, interpolator), "UTF-8"); // Compare text lines without regard to EOL delimiters assertEquals(FileUtils.readLines(expectedDockerFile), FileUtils.readLines(actualDockerFile)); @@ -88,7 +87,7 @@ private File getDockerfilePath(int i, String dir) { String.format("interpolate/%s/Dockerfile_%d", dir, i)).getFile()); } - private MojoParameters mockMojoParams() { + private MavenBuildContext mockMavenBuildContext() { MavenProject project = new MavenProject(); project.setArtifactId("docker-maven-plugin"); @@ -108,6 +107,14 @@ public String getBasedir() { MavenSession session = new MavenSession(null, settings, localRepository, null, null, Collections.emptyList(), ".", null, null, new Date(System.currentTimeMillis())); session.getUserProperties().setProperty("cliOverride", "cliValue"); // Maven CLI override: -DcliOverride=cliValue session.getSystemProperties().put("user.name", "somebody"); // Java system property: -Duser.name=somebody - return new MojoParameters(session, project, null, null, null, settings, "src", "target", Collections.singletonList(project)); + + return new MavenBuildContext.Builder() + .project(project) + .settings(settings) + .session(session) + .sourceDirectory("src") + .outputDirectory("target") + .reactorProjects(Collections.singletonList(project)) + .build(); } } diff --git a/src/test/resources/io/fabric8/maven/docker/util/openshift_nologin_config.yaml b/src/test/resources/io/fabric8/maven/docker/build/maven/openshift_nologin_config.yaml similarity index 100% rename from src/test/resources/io/fabric8/maven/docker/util/openshift_nologin_config.yaml rename to src/test/resources/io/fabric8/maven/docker/build/maven/openshift_nologin_config.yaml diff --git a/src/test/resources/io/fabric8/maven/docker/util/openshift_simple_config.yaml b/src/test/resources/io/fabric8/maven/docker/build/maven/openshift_simple_config.yaml similarity index 100% rename from src/test/resources/io/fabric8/maven/docker/util/openshift_simple_config.yaml rename to src/test/resources/io/fabric8/maven/docker/build/maven/openshift_simple_config.yaml