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.PushImageCmd;
019import com.github.dockerjava.api.model.AuthConfig;
020import com.google.cloud.tools.jib.api.Credential;
021import com.google.cloud.tools.jib.maven.MavenProjectProperties;
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.plugin.MojoFailureException;
029import org.apache.maven.plugins.annotations.Mojo;
030import org.apache.maven.project.MavenProject;
031import org.slf4j.Logger;
032import org.slf4j.LoggerFactory;
033
034import javax.inject.Inject;
035import java.util.Optional;
036import java.util.Set;
037
038/**
039 * <p>Implementation of the <code>deploy</code> lifecycle for pushing Docker images</p>
040 * <p><strong>WARNING</strong>: this goal is not intended to be executed directly. Instead, Execute the <code>deploy</code>
041 * phase specifying the packaging type, eg:</p>
042 *
043 * <pre>mvn deploy -Dpackaging=docker-native</pre>
044 *
045 * @author Álvaro Sánchez-Mariscal
046 * @since 1.1
047 */
048@Mojo(name = "docker-push")
049public class DockerPushMojo extends AbstractDockerMojo {
050
051    private static final Logger LOG = LoggerFactory.getLogger(DockerPushMojo.class);
052
053    @Inject
054    public DockerPushMojo(MavenProject mavenProject, JibConfigurationService jibConfigurationService,
055                          ApplicationConfigurationService applicationConfigurationService, DockerService dockerService,
056                          MavenSession mavenSession, MojoExecution mojoExecution) {
057        super(mavenProject, jibConfigurationService, applicationConfigurationService, dockerService, mavenSession, mojoExecution);
058    }
059
060    @Override
061    public void execute() throws MojoExecutionException, MojoFailureException {
062        Packaging packaging = Packaging.of(mavenProject.getPackaging());
063        if (packaging == Packaging.DOCKER || packaging == Packaging.DOCKER_NATIVE || packaging == Packaging.DOCKER_CRAC) {
064            Set<String> images = getTags();
065
066            // getTags() will automatically generate an image name if none is specified
067            // To maintain error compatibility, check that an image name has been
068            // manually specified.
069            if (jibConfigurationService.getToImage().isPresent()) {
070                for (String taggedImage : images) {
071                    getLog().info("Pushing image: " + taggedImage);
072                    try (PushImageCmd pushImageCmd = dockerService.pushImageCmd(taggedImage)) {
073                        Optional<Credential> toCredentials = jibConfigurationService.getToCredentials();
074                        Optional<Credential> credential = toCredentials.or(() -> jibConfigurationService.resolveCredentialForImage(taggedImage, LOG));
075                        credential.ifPresent(cred -> {
076                            var username = cred.getUsername();
077                            var password = cred.getPassword();
078                            AuthConfig authConfig = dockerService.getAuthConfigFor(taggedImage, username, password);
079                            pushImageCmd.withAuthConfig(authConfig);
080                        });
081
082                        pushImageCmd.start().awaitCompletion();
083                    } catch (InterruptedException e) {
084                        Thread.currentThread().interrupt();
085                    } catch (Exception e) {
086                        throw new MojoExecutionException(e.getMessage(), e);
087                    }
088                }
089            } else {
090                throw new MojoFailureException("The plugin " + MavenProjectProperties.PLUGIN_KEY + " is misconfigured. Missing <to> tag");
091            }
092        } else {
093            throw new MojoFailureException("The <packaging> must be set to either [" + Packaging.DOCKER.id() + "] or [" + Packaging.DOCKER_NATIVE.id() + "]");
094        }
095    }
096
097}