package org.jfrog.hudson.pipeline.steps;
import com.google.inject.Inject;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.Run;
import hudson.model.TaskListener;
import org.apache.commons.cli.MissingArgumentException;
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution;
import org.jenkinsci.plugins.workflow.steps.StepContextParameter;
import org.jfrog.hudson.CredentialsConfig;
import org.jfrog.hudson.pipeline.Utils;
import org.jfrog.hudson.pipeline.docker.proxy.BuildInfoProxy;
import org.jfrog.hudson.pipeline.docker.utils.DockerAgentUtils;
import org.jfrog.hudson.pipeline.types.buildInfo.BuildInfo;
import org.jfrog.hudson.util.JenkinsBuildInfoLog;
import org.kohsuke.stapler.DataBoundConstructor;
/**
* Created by romang on 5/2/16.
*/
public class DockerPushStep extends AbstractStepImpl {
private final String image;
private CredentialsConfig credentialsConfig;
private String host;
private BuildInfo buildInfo;
private String targetRepo;
@DataBoundConstructor
public DockerPushStep(String image, CredentialsConfig credentialsConfig, String host, String targetRepo, BuildInfo buildInfo) {
this.image = image;
this.credentialsConfig = credentialsConfig;
this.host = host;
this.buildInfo = buildInfo;
this.targetRepo = targetRepo;
}
public String getImage() {
return image;
}
public CredentialsConfig getCredentialsConfig() {
return credentialsConfig;
}
public String getHost() {
return host;
}
public BuildInfo getBuildInfo() {
return buildInfo;
}
public String getTargetRepo() {
return targetRepo;
}
public static class Execution extends AbstractSynchronousNonBlockingStepExecution<BuildInfo> {
private static final long serialVersionUID = 1L;
@Inject(optional = true)
private transient DockerPushStep step;
@StepContextParameter
private transient TaskListener listener;
@StepContextParameter
private transient Run build;
@StepContextParameter
private transient Launcher launcher;
@StepContextParameter
private transient FilePath ws;
@Override
protected BuildInfo run() throws Exception {
if (!BuildInfoProxy.isUp()) {
getContext().onFailure(new RuntimeException("Build info capturing for Docker images is not available while Artifactory proxy is not running, enable the proxy in Jenkins configuration."));
return null;
}
if (step.getImage() == null) {
getContext().onFailure(new MissingArgumentException("Missing 'image' parameter"));
return null;
}
if (step.getTargetRepo() == null) {
getContext().onFailure(new MissingArgumentException("Missing 'targetRepo' parameter"));
return null;
}
BuildInfo buildInfo = Utils.prepareBuildinfo(build, step.getBuildInfo());
DockerAgentUtils.registerImageOnAgents(launcher, step.getImage(), step.getHost(), step.getTargetRepo(), buildInfo.hashCode());
String username = step.getCredentialsConfig().provideUsername(build.getParent());
String password = step.getCredentialsConfig().providePassword(build.getParent());
JenkinsBuildInfoLog log = new JenkinsBuildInfoLog(listener);
DockerAgentUtils.pushImage(launcher, log, step.getImage(), username, password, step.getHost());
if (!DockerAgentUtils.updateImageParentOnAgents(log, step.getImage(), step.getHost(), buildInfo.hashCode())) {
getContext().onFailure(new IllegalStateException("Build info capturing failed for docker image: " +
step.getImage() + " check build info proxy configuration."));
return null;
}
log.info("Successfully pushed docker image: " + step.getImage());
return buildInfo;
}
}
@Extension
public static final class DescriptorImpl extends AbstractStepDescriptorImpl {
public DescriptorImpl() {
super(DockerPushStep.Execution.class);
}
@Override
public String getFunctionName() {
return "dockerPushStep";
}
@Override
public String getDisplayName() {
return "Artifactory docker push";
}
@Override
public boolean isAdvanced() {
return true;
}
}
}