001/*
002 * Copyright 2017-2022 original authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.micronaut.maven;
017
018import com.github.dockerjava.api.command.BuildImageCmd;
019import com.google.cloud.tools.jib.plugins.common.PropertyNames;
020import io.micronaut.maven.core.DockerBuildStrategy;
021import io.micronaut.maven.core.MicronautRuntime;
022import io.micronaut.maven.jib.JibConfigurationService;
023import io.micronaut.maven.services.ApplicationConfigurationService;
024import io.micronaut.maven.services.DockerService;
025import org.apache.maven.execution.MavenSession;
026import org.apache.maven.plugin.MojoExecution;
027import org.apache.maven.plugin.MojoExecutionException;
028import org.apache.maven.plugins.annotations.Mojo;
029import org.apache.maven.plugins.annotations.ResolutionScope;
030import org.apache.maven.project.MavenProject;
031
032import javax.inject.Inject;
033import java.io.File;
034import java.io.IOException;
035import java.nio.file.Files;
036import java.nio.file.LinkOption;
037import java.nio.file.StandardCopyOption;
038
039import static io.micronaut.maven.DockerfileMojo.DOCKERFILE_ORACLE_CLOUD;
040
041/**
042 * <p>Allows using a provided Dockerfile.</p>
043 * <p><strong>WARNING</strong>: this goal is not intended to be executed directly. Instead, specify the packaging type
044 * using the <code>packaging</code> property, eg:</p>
045 *
046 * <pre>mvn package -Dpackaging=docker</pre>
047 *
048 * @author Álvaro Sánchez-Mariscal
049 * @since 1.1
050 */
051@Mojo(name = DockerMojo.DOCKER_PACKAGING, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
052public class DockerMojo extends AbstractDockerMojo {
053
054    public static final String DOCKER_PACKAGING = "docker";
055
056    @SuppressWarnings("CdiInjectionPointsInspection")
057    @Inject
058    public DockerMojo(MavenProject mavenProject, JibConfigurationService jibConfigurationService,
059                      ApplicationConfigurationService applicationConfigurationService, DockerService dockerService,
060                      MavenSession mavenSession, MojoExecution mojoExecution) {
061        super(mavenProject, jibConfigurationService, applicationConfigurationService, dockerService, mavenSession,
062            mojoExecution);
063    }
064
065    @Override
066    public void execute() throws MojoExecutionException {
067        var providedDockerfile = new File(mavenProject.getBasedir(), DockerfileMojo.DOCKERFILE);
068        if (shouldBuildWithDockerfile(providedDockerfile)) {
069            var dockerfile = determineDockerfile(providedDockerfile);
070            buildDockerfile(dockerfile);
071        } else if (jibConfigurationService.getFromImage().isEmpty()) {
072            mavenProject.getProperties().setProperty(PropertyNames.FROM_IMAGE, getBaseImage());
073        }
074    }
075
076    private File determineDockerfile(File providedDockerfile) throws MojoExecutionException {
077        if (providedDockerfile.exists()) {
078            return providedDockerfile;
079        }
080        try {
081            return dockerService.loadDockerfileAsResource(DOCKERFILE_ORACLE_CLOUD);
082        } catch (IOException e) {
083            throw new MojoExecutionException("Error loading Dockerfile", e);
084        }
085    }
086
087    private boolean shouldBuildWithDockerfile(File providedDockerfile) {
088        var runtime = MicronautRuntime.valueOf(micronautRuntime.toUpperCase());
089        return providedDockerfile.exists() || runtime.getBuildStrategy() == DockerBuildStrategy.ORACLE_FUNCTION;
090    }
091
092    private void buildDockerfile(File dockerfile) throws MojoExecutionException {
093        try {
094            var runtime = MicronautRuntime.valueOf(micronautRuntime.toUpperCase());
095            if (runtime.getBuildStrategy() == DockerBuildStrategy.ORACLE_FUNCTION) {
096                oracleCloudFunctionCmd(dockerfile);
097                DockerfileMojo.processOracleFunctionDockerfile(dockerfile);
098            }
099            getLog().info("Using Dockerfile: " + dockerfile.getAbsolutePath());
100            mavenProject.getProperties().put(PropertyNames.SKIP, "true");
101
102            copyDependencies();
103
104            String targetDir = mavenProject.getBuild().getDirectory();
105            var targetDockerfile = new File(targetDir, dockerfile.getName());
106            Files.copy(dockerfile.toPath(), targetDockerfile.toPath(), LinkOption.NOFOLLOW_LINKS,
107                StandardCopyOption.REPLACE_EXISTING);
108
109            BuildImageCmd buildImageCmd = dockerService.buildImageCmd()
110                .withDockerfile(targetDockerfile)
111                .withTags(getTags())
112                .withBaseDirectory(new File(targetDir));
113            getNetworkMode().ifPresent(buildImageCmd::withNetworkMode);
114            dockerService.buildImage(buildImageCmd);
115        } catch (IOException e) {
116            throw new MojoExecutionException(e.getMessage(), e);
117        }
118    }
119
120}