Java tutorial
/* * Copyright 2016 Red Hat, Inc. * * Red Hat licenses this file to you under the Apache License, version * 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package io.fabric8.maven.plugin.mojo.build; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Objects; import java.util.Properties; import io.fabric8.kubernetes.api.model.KubernetesListBuilder; import io.fabric8.maven.core.access.ClusterAccess; import io.fabric8.maven.core.config.BuildRecreateMode; import io.fabric8.maven.core.config.OpenShiftBuildStrategy; import io.fabric8.maven.core.config.PlatformMode; import io.fabric8.maven.core.config.ProcessorConfig; import io.fabric8.maven.core.config.ResourceConfig; import io.fabric8.maven.core.service.BuildService; import io.fabric8.maven.core.service.Fabric8ServiceHub; import io.fabric8.maven.core.util.GoalFinder; import io.fabric8.maven.core.util.Gofabric8Util; import io.fabric8.maven.core.util.OpenShiftDependencyResources; import io.fabric8.maven.core.util.ProfileUtil; import io.fabric8.maven.docker.access.DockerAccessException; import io.fabric8.maven.docker.config.ImageConfiguration; import io.fabric8.maven.docker.service.DockerAccessFactory; import io.fabric8.maven.docker.service.ServiceHub; import io.fabric8.maven.docker.util.EnvUtil; import io.fabric8.maven.docker.util.Task; import io.fabric8.maven.enricher.api.EnricherContext; import io.fabric8.maven.generator.api.GeneratorContext; import io.fabric8.maven.plugin.enricher.EnricherManager; import io.fabric8.maven.plugin.generator.GeneratorManager; import org.apache.commons.lang3.StringUtils; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProjectHelper; import org.apache.maven.repository.RepositorySystem; /** * Builds the docker images configured for this project via a Docker or S2I binary build. * * @author roland * @since 16/03/16 */ @Mojo(name = "build", defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST, requiresDependencyResolution = ResolutionScope.COMPILE) public class BuildMojo extends io.fabric8.maven.docker.BuildMojo { /** * Generator specific options. This is a generic prefix where the keys have the form * <code><generator-prefix>-<option></code>. */ @Parameter private ProcessorConfig generator; /** * Enrichers used for enricher build objects */ @Parameter private ProcessorConfig enricher; /** * Resource config for getting annotation and labels to be applied to enriched build objects */ @Parameter private ResourceConfig resources; // To skip over the execution of the goal @Parameter(property = "fabric8.skip", defaultValue = "false") protected boolean skip; /** * Profile to use. A profile contains the enrichers and generators to * use as well as their configuration. Profiles are looked up * in the classpath and can be provided as yaml files. * * However, any given enricher and or generator configuration overrides * the information provided by a profile. */ @Parameter(property = "fabric8.profile") private String profile; /** * Folder where to find project specific files, e.g a custom profile */ @Parameter(property = "fabric8.resourceDir", defaultValue = "${basedir}/src/main/fabric8") private File resourceDir; @Parameter(property = "fabric8.skip.build.pom", defaultValue = "true") private Boolean skipBuildPom; /** * Whether to perform a Kubernetes build (i.e. against a vanilla Docker daemon) or * an OpenShift build (with a Docker build against the OpenShift API server. */ @Parameter(property = "fabric8.mode") private PlatformMode mode = PlatformMode.DEFAULT; /** * OpenShift build mode when an OpenShift build is performed. * Can be either "s2i" for an s2i binary build mode or "docker" for a binary * docker mode. */ @Parameter(property = "fabric8.build.strategy") private OpenShiftBuildStrategy buildStrategy = OpenShiftBuildStrategy.s2i; /** * The S2I binary builder BuildConfig name suffix appended to the image name to avoid * clashing with the underlying BuildConfig for the Jenkins pipeline */ @Parameter(property = "fabric8.s2i.buildNameSuffix", defaultValue = "-s2i") private String s2iBuildNameSuffix; /** * The name of pullSecret to be used to pull the base image in case pulling from a private * registry which requires authentication. */ @Parameter(property = "fabric8.build.pullSecret", defaultValue = "pullsecret-fabric8") private String openshiftPullSecret; /** * Allow the ImageStream used in the S2I binary build to be used in standard * Kubernetes resources such as Deployment or StatefulSet. */ @Parameter(property = "fabric8.s2i.imageStreamLookupPolicyLocal", defaultValue = "true") private boolean s2iImageStreamLookupPolicyLocal = true; /** * Should we use the project's compile-time classpath to scan for additional enrichers/generators? */ @Parameter(property = "fabric8.useProjectClasspath", defaultValue = "false") private boolean useProjectClasspath = false; /** * How to recreate the build config and/or image stream created by the build. * Only in effect when <code>mode == openshift</code> or mode is <code>auto</code> * and openshift is detected. If not set, existing * build config will not be recreated. * * The possible values are: * * <ul> * <li><strong>buildConfig</strong> or <strong>bc</strong> : * Only the build config is recreated</li> * <li><strong>imageStream</strong> or <strong>is</strong> : * Only the image stream is recreated</li> * <li><strong>all</strong> : Both, build config and image stream are recreated</li> * <li><strong>none</strong> : Neither build config nor image stream is recreated</li> * </ul> */ @Parameter(property = "fabric8.build.recreate", defaultValue = "none") private String buildRecreate; /** * Namespace to use when accessing Kubernetes or OpenShift */ @Parameter(property = "fabric8.namespace") private String namespace; // Used for determining which mojos are called during a run @Component protected GoalFinder goalFinder; @Component private MavenProjectHelper projectHelper; @Component protected RepositorySystem repositorySystem; // Access for creating OpenShift binary builds private ClusterAccess clusterAccess; // The Fabric8 service hub Fabric8ServiceHub fabric8ServiceHub; // Mode which is resolved, also when 'auto' is set private PlatformMode platformMode; @Override public void execute() throws MojoExecutionException, MojoFailureException { if (skip || skipBuild) { return; } clusterAccess = new ClusterAccess(namespace); // Platform mode is already used in executeInternal() super.execute(); } @Override protected boolean isDockerAccessRequired() { return platformMode == PlatformMode.kubernetes; } @Override protected void executeInternal(ServiceHub hub) throws DockerAccessException, MojoExecutionException { if (shouldSkipBecauseOfPomPackaging()) { getLog().info("Disabling docker build for pom packaging"); return; } if (getResolvedImages().size() == 0) { log.warn("No image build configuration found or detected"); } // Build the fabric8 service hub fabric8ServiceHub = new Fabric8ServiceHub.Builder().log(log).clusterAccess(clusterAccess).platformMode(mode) .dockerServiceHub(hub).buildServiceConfig(getBuildServiceConfig()) .repositorySystem(repositorySystem).mavenProject(project).build(); super.executeInternal(hub); fabric8ServiceHub.getBuildService().postProcess(getBuildServiceConfig()); } private boolean shouldSkipBecauseOfPomPackaging() { if (!Objects.equals("pom", project.getPackaging())) { // No pom packaging return false; } if (skipBuildPom != null) { // If configured take the config option return skipBuildPom; } // Not specified: Skip if no image with build configured, otherwise don't skip for (ImageConfiguration image : getResolvedImages()) { if (image.getBuildConfiguration() != null) { return false; } } return true; } @Override protected DockerAccessFactory.DockerAccessContext getDockerAccessContext() { return new DockerAccessFactory.DockerAccessContext.Builder(super.getDockerAccessContext()) .dockerHostProviders(Gofabric8Util.extractDockerHostProvider(log)).build(); } @Override protected void buildAndTag(ServiceHub hub, ImageConfiguration imageConfig) throws MojoExecutionException, DockerAccessException { try { // TODO need to refactor d-m-p to avoid this call EnvUtil.storeTimestamp(this.getBuildTimestampFile(), this.getBuildTimestamp()); fabric8ServiceHub.getBuildService().build(imageConfig); } catch (Exception ex) { throw new MojoExecutionException("Failed to execute the build", ex); } } protected io.fabric8.maven.core.service.BuildService.BuildServiceConfig getBuildServiceConfig() throws MojoExecutionException { return new io.fabric8.maven.core.service.BuildService.BuildServiceConfig.Builder() .dockerBuildContext(getBuildContext()).dockerMojoParameters(createMojoParameters()) .buildRecreateMode(BuildRecreateMode.fromParameter(buildRecreate)) .openshiftBuildStrategy(buildStrategy).openshiftPullSecret(openshiftPullSecret) .s2iBuildNameSuffix(s2iBuildNameSuffix) .s2iImageStreamLookupPolicyLocal(s2iImageStreamLookupPolicyLocal) .buildDirectory(project.getBuild().getDirectory()) .attacher(new BuildService.BuildServiceConfig.Attacher() { @Override public void attach(String classifier, File destFile) { if (destFile.exists()) { projectHelper.attachArtifact(project, "yml", classifier, destFile); } } }).enricherTask(new Task<KubernetesListBuilder>() { @Override public void execute(KubernetesListBuilder builder) throws Exception { new EnricherManager(resources, getEnricherContext()).enrich(builder); } }).build(); } /** * Customization hook called by the base plugin. * * @param configs configuration to customize * @return the configuration customized by our generators. */ @Override public List<ImageConfiguration> customizeConfig(List<ImageConfiguration> configs) { platformMode = clusterAccess.resolvePlatformMode(mode, log); if (platformMode == PlatformMode.openshift) { log.info("Using [[B]]OpenShift[[B]] build with strategy [[B]]%s[[B]]", buildStrategy.getLabel()); } else { log.info("Building Docker image in [[B]]Kubernetes[[B]] mode"); } if (platformMode.equals(PlatformMode.openshift)) { Properties properties = project.getProperties(); if (!properties.contains(PlatformMode.FABRIC8_EFFECTIVE_PLATFORM_MODE)) { properties.setProperty(PlatformMode.FABRIC8_EFFECTIVE_PLATFORM_MODE, platformMode.toString()); } } try { return GeneratorManager.generate(configs, getGeneratorContext(), false); } catch (MojoExecutionException e) { throw new IllegalArgumentException("Cannot extract generator config: " + e, e); } } @Override protected String getLogPrefix() { return "F8: "; } // ================================================================================================== // Get generator context private GeneratorContext getGeneratorContext() { return new GeneratorContext.Builder().config(extractGeneratorConfig()).project(project).session(session) .goalFinder(goalFinder).goalName("fabric8:build").logger(log).mode(platformMode) .strategy(buildStrategy).useProjectClasspath(useProjectClasspath) .artifactResolver(getFabric8ServiceHub().getArtifactResolverService()).build(); } private Fabric8ServiceHub getFabric8ServiceHub() { return new Fabric8ServiceHub.Builder().log(log).clusterAccess(clusterAccess).platformMode(mode) .repositorySystem(repositorySystem).mavenProject(project).build(); } // Get generator config private ProcessorConfig extractGeneratorConfig() { try { return ProfileUtil.blendProfileWithConfiguration(ProfileUtil.GENERATOR_CONFIG, profile, resourceDir, generator); } catch (IOException e) { throw new IllegalArgumentException("Cannot extract generator config: " + e, e); } } // Get enricher context public EnricherContext getEnricherContext() { return new EnricherContext.Builder().project(project).session(session).goalFinder(goalFinder) .config(extractEnricherConfig()).images(getResolvedImages()).resources(resources) .namespace(resources != null && resources.getNamespace() != null ? resources.getNamespace() : namespace) .log(log).openshiftDependencyResources(new OpenShiftDependencyResources(log)) .useProjectClasspath(useProjectClasspath).build(); } // Get enricher config private ProcessorConfig extractEnricherConfig() { try { return ProfileUtil.blendProfileWithConfiguration(ProfileUtil.ENRICHER_CONFIG, profile, resourceDir, enricher); } catch (IOException e) { throw new IllegalArgumentException("Cannot extract enricher config: " + e, e); } } }