/*************************GO-LICENSE-START*********************************
* Copyright 2014 ThoughtWorks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*************************GO-LICENSE-END***********************************/
package com.thoughtworks.go.domain;
import com.thoughtworks.go.config.*;
import com.thoughtworks.go.server.service.InstanceFactory;
import com.thoughtworks.go.util.Clock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @understands how to match job instances associated with run-multiple-instance Jobs
*/
public class RunMultipleInstance implements JobType {
private static final Pattern CONFIG_NAME_PATTERN = Pattern.compile("^(.+?)-" + RunMultipleInstanceJobTypeConfig.MARKER + "-\\d+$");
private final JobTypeConfig jobTypeConfig = new RunMultipleInstanceJobTypeConfig();
@Override
public boolean isInstanceOf(String jobInstanceName, boolean ignoreCase, String jobConfigName) {
return jobTypeConfig.isInstanceOf(jobInstanceName, ignoreCase, jobConfigName);
}
public void createRerunInstances(JobInstance oldJob, JobInstances jobInstances, SchedulingContext context, StageConfig stageConfig, final Clock clock, InstanceFactory instanceFactory) {
context = context.rerunContext();
String configName = translateToConfigName(oldJob.getName());
JobConfig jobConfig = stageConfig.jobConfigByConfigName(new CaseInsensitiveString(configName));
if (jobConfig == null) {
throw new CannotRerunJobException(configName, "Configuration for job doesn't exist.");
}
if (!jobConfig.isRunMultipleInstanceType()) {
String runType = jobConfig.isRunOnAllAgents() ? "'run on all agents'" : "'simple'";
throw new CannotRerunJobException(configName, "Run configuration for job has been changed to " + runType + ".");
}
String newJobName = oldJob.getName();
JobInstances instances = instanceFactory.createJobInstance(stageConfig.name(), jobConfig, context, clock, new IdentityNameGenerator(newJobName));
for (JobInstance instance : instances) {
instance.setRerun(true);
}
jobInstances.addAll(instances);
}
private String translateToConfigName(String jobName) {
Matcher matcher = CONFIG_NAME_PATTERN.matcher(jobName);
if (matcher.matches()) {
return matcher.group(1);
} else {
throw new IllegalArgumentException(String.format("Job name '%s' does not match the pattern for 'run multiple instance' job", jobName));
}
}
public void createJobInstances(JobInstances jobs, SchedulingContext context, JobConfig config, String stageName, final JobNameGenerator nameGenerator, final Clock clock, InstanceFactory instanceFactory) {
Integer totalInstances = context.isRerun() ? 1 : config.getRunInstanceCountValue();
for (int counter = 1; counter <= totalInstances; counter++) {
String jobName = nameGenerator.generateName(counter);
context = setEnvironmentVariables(context, config, jobName, counter);
instanceFactory.reallyCreateJobInstance(config, jobs, null, jobName, false, true, context, clock);
}
}
private SchedulingContext setEnvironmentVariables(SchedulingContext context, JobConfig config, String jobName, int counter) {
EnvironmentVariablesConfig environmentVariablesConfig = new EnvironmentVariablesConfig();
int index = context.isRerun() ? getOldJobIndex(jobName) : counter;
environmentVariablesConfig.add(new EnvironmentVariableConfig("GO_JOB_RUN_INDEX", Integer.toString(index)));
environmentVariablesConfig.add(new EnvironmentVariableConfig("GO_JOB_RUN_COUNT", Integer.toString(config.getRunInstanceCountValue())));
context = context.overrideEnvironmentVariables(environmentVariablesConfig);
return context;
}
private Integer getOldJobIndex(String jobName) {
return Integer.valueOf(jobName.split("-" + RunMultipleInstanceJobTypeConfig.MARKER + "-")[1]);
}
private static class IdentityNameGenerator implements JobNameGenerator {
private final String name;
private IdentityNameGenerator(String name) {
this.name = name;
}
public String generateName(int counter) {
return name;
}
}
public static class CounterBasedJobNameGenerator implements JobNameGenerator {
private String name;
public CounterBasedJobNameGenerator(String name) {
this.name = name;
}
public String generateName(final int counter) {
return appendMarker(name, counter);
}
public static String appendMarker(final String name, int counter) {
return String.format("%s-%s-%s", name, RunMultipleInstanceJobTypeConfig.MARKER, counter);
}
}
}