package org.jenkinsci.plugins.ansible.workflow;
import com.cloudbees.jenkins.plugins.sshcredentials.SSHUserPrivateKey;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials;
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
import com.google.inject.Inject;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.model.Computer;
import hudson.model.Project;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.util.ListBoxModel;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.ansible.AnsibleInstallation;
import org.jenkinsci.plugins.ansible.AnsiblePlaybookBuilder;
import org.jenkinsci.plugins.ansible.Inventory;
import org.jenkinsci.plugins.ansible.InventoryPath;
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousStepExecution;
import org.jenkinsci.plugins.workflow.steps.StepContextParameter;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import static com.cloudbees.plugins.credentials.CredentialsMatchers.anyOf;
import static com.cloudbees.plugins.credentials.CredentialsMatchers.instanceOf;
/**
* The Ansible playbook invocation step for the Jenkins workflow plugin.
*/
public class AnsiblePlaybookStep extends AbstractStepImpl {
private final String playbook;
private String inventory;
private String installation;
private String credentialsId;
private boolean sudo = false;
private String sudoUser = "root";
private String limit = null;
private String tags = null;
private String skippedTags = null;
private String startAtTask = null;
private String extras = null;
@DataBoundConstructor
public AnsiblePlaybookStep(String playbook) {
this.playbook = playbook;
}
@DataBoundSetter
public void setInventory(String inventory) {
this.inventory = Util.fixEmptyAndTrim(inventory);
}
@DataBoundSetter
public void setCredentialsId(String credentialsId) {
this.credentialsId = Util.fixEmptyAndTrim(credentialsId);
}
@DataBoundSetter
public void setSudo(boolean sudo) {
this.sudo = sudo;
}
@DataBoundSetter
public void setSudoUser(String sudoUser) {
this.sudoUser = Util.fixEmptyAndTrim(sudoUser);
}
@DataBoundSetter
public void setInstallation(String installation) {
this.installation = Util.fixEmptyAndTrim(installation);
}
@DataBoundSetter
public void setLimit(String limit) {
this.limit = Util.fixEmptyAndTrim(limit);
}
@DataBoundSetter
public void setTags(String tags) {
this.tags = Util.fixEmptyAndTrim(tags);
}
@DataBoundSetter
public void setSkippedTags(String skippedTags) {
this.skippedTags = Util.fixEmptyAndTrim(skippedTags);
}
@DataBoundSetter
public void setStartAtTask(String startAtTask) {
this.startAtTask = Util.fixEmptyAndTrim(startAtTask);
}
@DataBoundSetter
public void setExtras(String extras) {
this.extras = Util.fixEmptyAndTrim(extras);
}
public String getInstallation() {
return installation;
}
public String getPlaybook() {
return playbook;
}
public String getInventory() {
return inventory;
}
public String getCredentialsId() {
return credentialsId;
}
public boolean isSudo() {
return sudo;
}
public String getSudoUser() {
return sudoUser;
}
public String getLimit() {
return limit;
}
public String getTags() {
return tags;
}
public String getSkippedTags() {
return skippedTags;
}
public String getStartAtTask() {
return startAtTask;
}
public String getExtras() {
return extras;
}
@Extension
public static final class DescriptorImpl extends AbstractStepDescriptorImpl {
public DescriptorImpl() {
super(AnsiblePlaybookExecution.class);
}
@Override
public String getFunctionName() {
return "ansiblePlaybook";
}
@Override
public String getDisplayName() {
return "Invoke an ansible playbook";
}
public ListBoxModel doFillCredentialsIdItems(@AncestorInPath Project project) {
return new StandardListBoxModel()
.withEmptySelection()
.withMatching(anyOf(
instanceOf(SSHUserPrivateKey.class),
instanceOf(UsernamePasswordCredentials.class)),
CredentialsProvider.lookupCredentials(StandardUsernameCredentials.class, project));
}
public ListBoxModel doFillInstallationItems() {
ListBoxModel model = new ListBoxModel();
for (AnsibleInstallation tool : AnsibleInstallation.allInstallations()) {
model.add(tool.getName());
}
return model;
}
}
public static final class AnsiblePlaybookExecution extends AbstractSynchronousStepExecution<Void> {
private static final long serialVersionUID = 1;
@Inject
private transient AnsiblePlaybookStep step;
@StepContextParameter
private transient TaskListener listener;
@StepContextParameter
private transient Launcher launcher;
@StepContextParameter
private transient Run<?,?> run;
@StepContextParameter
private transient FilePath ws;
@StepContextParameter
private transient EnvVars envVars;
@StepContextParameter
private transient Computer computer;
@Override
protected Void run() throws Exception {
Inventory inventory = StringUtils.isNotBlank(step.getInventory()) ? new InventoryPath(step.getInventory()) : null;
AnsiblePlaybookBuilder builder = new AnsiblePlaybookBuilder(step.getPlaybook(), inventory);
builder.setAnsibleName(step.getInstallation());
builder.setSudo(step.isSudo());
builder.setSudoUser(step.getSudoUser());
builder.setCredentialsId(step.getCredentialsId(), true);
builder.setForks(5);
builder.setLimit(step.getLimit());
builder.setTags(step.getTags());
builder.setStartAtTask(step.getStartAtTask());
builder.setSkippedTags(step.getSkippedTags());
builder.setAdditionalParameters(step.getExtras());
builder.setHostKeyChecking(false);
builder.setUnbufferedOutput(true);
builder.setColorizedOutput(false);
builder.perform(run, computer.getNode(), ws, launcher, listener, envVars);
return null;
}
}
}