package de.codecentric.jenkins.dashboard; import hudson.Extension; import hudson.Launcher; import hudson.Util; import hudson.model.BuildListener; import hudson.model.ParameterValue; import hudson.model.AbstractBuild; import hudson.model.Descriptor; import hudson.model.ParametersAction; import hudson.security.ACL; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import hudson.util.ListBoxModel; import java.util.List; import jenkins.model.Jenkins; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.StaplerRequest; import com.amazonaws.regions.Region; import com.amazonaws.regions.Regions; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.domains.DomainRequirement; import de.codecentric.jenkins.dashboard.ec2.AwsKeyCredentials; import de.codecentric.jenkins.dashboard.impl.deploy.DeployJobVariables; import de.codecentric.jenkins.dashboard.impl.deploy.DeployJobVariablesBuilder; import de.codecentric.jenkins.dashboard.impl.environments.ec2.AwsRegion; import de.codecentric.jenkins.dashboard.impl.environments.ec2.EC2Connector; /** * This {@link Builder} tags the specified environment with a given version * number. * * <p> * When the user configures the project and enable this builder, * {@link DescriptorImpl#newInstance(StaplerRequest)} is invoked and a new * {@link EnvironmentTagBuilder} is created. The created instance is persisted * to the project configuration XML by using XStream, so this allows you to use * instance fields (like {@link #credentials}) to remember the configuration. * </p> * * <p> * When a build is performed, the * {@link #perform(Build, Launcher, BuildListener)} method will be invoked. * </p> * * @author marcel.birkner * */ public class EnvironmentTagBuilder extends Builder { private String credentials; private String region; /** * This annotation tells Hudson to call this constructor, with values from * the configuration form page with matching parameter names. * * @param credentials reference to Jenkins AWS credentials * @param region reference to AWS region */ @DataBoundConstructor public EnvironmentTagBuilder(final String credentials, final String region) { this.setCredentials(credentials); this.setRegion(region); } public String getCredentials() { return credentials; } public void setCredentials(String credentials) { this.credentials = credentials; } public String getRegion() { return region; } public void setRegion(String region) { this.region = region; } /** * We'll use this from the <tt>config.jelly</tt>. */ @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) { DeployJobVariables jobVariables = extractDeployJobVariables(build); String message = region + " Tagging ENVIRONMENT [" + jobVariables.getEnvironment() + "] with VERSION [" + jobVariables.getVersion() + "]"; listener.getLogger().println(message); EC2Connector connector = EC2Connector.getEC2Connector(getCredentials()); boolean taggingSuccessful = connector.tagEnvironmentWithVersion(Region.getRegion(Regions.fromName(region)), jobVariables); if (!taggingSuccessful) { String failedMessage = "ERROR: Could not tag ENVIRONMENT [" + jobVariables.getEnvironment() + "] with VERSION [" + jobVariables.getVersion() + "]"; listener.getLogger().println(failedMessage); } return taggingSuccessful; } private DeployJobVariables extractDeployJobVariables(AbstractBuild build) { String environment = DeployJobVariablesBuilder.UNDEFINED; String version = DeployJobVariablesBuilder.UNDEFINED; List<ParametersAction> actionList = Util.filter(build.getAllActions(), ParametersAction.class); for (ParametersAction parametersAction : actionList) { List<ParameterValue> params = parametersAction.getParameters(); for (ParameterValue parameterValue : params) { if (DashboardView.PARAM_ENVIRONMENT.equalsIgnoreCase((String) parameterValue.getName())) { environment = (String) parameterValue.getValue(); } if (DashboardView.PARAM_VERSION.equalsIgnoreCase((String) parameterValue.getName())) { version = (String) parameterValue.getValue(); } } } return DeployJobVariablesBuilder.createBuilder().version(version).environment(environment).build(); } /** * Hudson defines a method {@link Builder#getDescriptor()}, which returns * the corresponding {@link Descriptor} object. * * Since we know that it's actually {@link DescriptorImpl}, override the * method and give a better return type, so that we can access * {@link DescriptorImpl} methods more easily. * * This is not necessary, but just a coding style preference. */ @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl) super.getDescriptor(); } /** * Descriptor for {@link EnvironmentTagBuilder}. The class is marked as * public so that it can be accessed from views. See * <tt>de/codecentric/jenkins/dashboard/EnvironmentTagBuilder/*.jelly</tt> * for the actual HTML fragment for the configuration screen. */ @Extension public static final class DescriptorImpl extends BuildStepDescriptor<Builder> { /** * To persist global configuration information, simply store it in a * field and call save(). * * <p> * If you don't want fields to be persisted, use <tt>transient</tt>. */ public DescriptorImpl() { load(); } public ListBoxModel doFillCredentialsItems() { final ListBoxModel model = new ListBoxModel(); DomainRequirement domain = new DomainRequirement(); for (AwsKeyCredentials credentials : CredentialsProvider.lookupCredentials(AwsKeyCredentials.class, Jenkins.getInstance(), ACL.SYSTEM, domain)) { model.add(credentials.getId()); } return model; } public ListBoxModel doFillRegionItems() { final ListBoxModel model = new ListBoxModel(); for (AwsRegion value : AwsRegion.values()) { model.add(value.getName(), value.getIdentifier()); } return model; } /** * This human readable name is used in the configuration screen. */ @Override public String getDisplayName() { return Messages.Environment_DisplayName(); } /** * Applicable to any kind of project. */ @Override public boolean isApplicable(Class type) { return true; } } }