/* * Copyright 2015 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. */ package com.thoughtworks.go.config; import com.thoughtworks.go.config.preprocessor.SkipParameterResolution; import com.thoughtworks.go.config.validation.NameTypeValidator; import com.thoughtworks.go.domain.ConfigErrors; import com.thoughtworks.go.service.TaskFactory; import com.thoughtworks.go.util.GoConstants; import java.util.List; import java.util.Map; /** * @understands the configuration for a stage */ @ConfigTag("stage") public class StageConfig implements Validatable, ParamsAttributeAware, EnvironmentVariableScope { @SkipParameterResolution @ConfigAttribute(value = "name", optional = false) private CaseInsensitiveString name; @ConfigAttribute(value = "fetchMaterials") private boolean fetchMaterials = DEFAULT_FETCH_MATERIALS; @ConfigAttribute(value = "artifactCleanupProhibited") private boolean artifactCleanupProhibited = false; @ConfigAttribute(value = "cleanWorkingDir") private boolean cleanWorkingDir = DEFAULT_CLEAN_WORKING_DIR; @ConfigSubtag(optional = true) private Approval approval = Approval.automaticApproval(); @ConfigSubtag private EnvironmentVariablesConfig variables = new EnvironmentVariablesConfig(); @ConfigSubtag(optional = false) private JobConfigs jobConfigs; private ConfigErrors errors = new ConfigErrors(); public static final boolean DEFAULT_FETCH_MATERIALS = true; public static final boolean DEFAULT_CLEAN_WORKING_DIR = false; public static final String NAME = "name"; public static final String APPROVAL = "approval"; public static final String JOBS = "jobs"; public static final String FETCH_MATERIALS = "fetchMaterials"; public static final String CLEAN_WORKING_DIR = "cleanWorkingDir"; public static final String ENVIRONMENT_VARIABLES = "variables"; public static final String OPERATE_USERS = "operateUsers"; public static final String OPERATE_ROLES = "operateRoles"; public static final String SECURITY_MODE = "securityMode"; public static final String DEFAULT_NAME = "defaultStage"; public static final String ARTIFACT_CLEANUP_PROHIBITED = "artifactCleanupProhibited"; public StageConfig() { } public StageConfig(final CaseInsensitiveString name, JobConfigs jobConfigs) { this(); this.name = name; this.jobConfigs = jobConfigs; } public StageConfig(final CaseInsensitiveString name, JobConfigs jobConfigs, Approval approval) { this(name, DEFAULT_FETCH_MATERIALS, DEFAULT_CLEAN_WORKING_DIR, approval, false, jobConfigs); } public StageConfig(final CaseInsensitiveString name, boolean fetchMaterials, boolean cleanWorkingDir, Approval approval, boolean artifactCleanupProhibited, JobConfigs jobConfigs) { this(name, jobConfigs); this.fetchMaterials = fetchMaterials; this.cleanWorkingDir = cleanWorkingDir; this.approval = approval; this.artifactCleanupProhibited = artifactCleanupProhibited; } public CaseInsensitiveString name() { return name; } public void setName(CaseInsensitiveString name) { this.name = name; } /* Used in view */ public boolean isFetchMaterials() { return fetchMaterials; } /* Used in view */ public boolean isCleanWorkingDir() { return cleanWorkingDir; } public JobConfig jobConfigByInstanceName(String jobInstanceName, boolean ignoreCase) { for (JobConfig jobConfig : jobConfigs) { if (jobConfig.isInstanceOf(jobInstanceName, ignoreCase)) { return jobConfig; } } return null; } public JobConfig jobConfigByConfigName(final CaseInsensitiveString jobName) { for (JobConfig jobConfig : jobConfigs) { if (jobConfig.name().equals(jobName)) { return jobConfig; } } return null; } public JobConfig jobConfigByConfigName(String jobName) { return jobConfigByConfigName(new CaseInsensitiveString(jobName)); } // TODO - #2491 - rename jobConfig to job public JobConfigs allBuildPlans() { return jobConfigs; } public String approvalType() { return requiresApproval() ? GoConstants.APPROVAL_MANUAL : GoConstants.APPROVAL_SUCCESS; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } StageConfig that = (StageConfig) o; if (fetchMaterials != that.fetchMaterials) { return false; } if (artifactCleanupProhibited != that.artifactCleanupProhibited) { return false; } if (cleanWorkingDir != that.cleanWorkingDir) { return false; } if (approval != null ? !approval.equals(that.approval) : that.approval != null) { return false; } if (jobConfigs != null ? !jobConfigs.equals(that.jobConfigs) : that.jobConfigs != null) { return false; } if (name != null ? !name.equals(that.name) : that.name != null) { return false; } if (variables != null ? !variables.equals(that.variables) : that.variables != null) { return false; } return true; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (fetchMaterials ? 1 : 0); result = 31 * result + (artifactCleanupProhibited ? 1 : 0); result = 31 * result + (cleanWorkingDir ? 1 : 0); result = 31 * result + (approval != null ? approval.hashCode() : 0); result = 31 * result + (variables != null ? variables.hashCode() : 0); result = 31 * result + (jobConfigs != null ? jobConfigs.hashCode() : 0); return result; } public boolean requiresApproval() { return approval.isManual(); } public void updateApproval(Approval approval) { this.approval = approval; } public boolean supportAutoApproval() { return !requiresApproval(); } public Approval getApproval() { return approval; } public void setApproval(Approval approval) { this.approval = approval; } public boolean hasOperatePermissionDefined() { return this.approval.isAuthorizationDefined(); } // only called from tests public void setVariables(EnvironmentVariablesConfig variables) { this.variables = variables; } public EnvironmentVariablesConfig getVariables() { return variables; } public EnvironmentVariablesConfig getPlainTextVariables() { return variables.getPlainTextVariables(); } public EnvironmentVariablesConfig getSecureVariables() { return variables.getSecureVariables(); } public boolean hasVariableInScope(String variableName) { if (variables.hasVariable(variableName)) { return true; } for (JobConfig jobConfig : jobConfigs) { if (jobConfig.hasVariable(variableName)) { return true; } } return false; } public boolean hasTests() { for (JobConfig job : jobConfigs) { if (job.hasTests()) { return true; } } return false; } public void setFetchMaterials(boolean fetchMaterials) { this.fetchMaterials = fetchMaterials; } public void setCleanWorkingDir(boolean cleanWorkingDir) { this.cleanWorkingDir = cleanWorkingDir; } public boolean validateTree(ValidationContext validationContext) { validate(validationContext); boolean isValid = errors.isEmpty(); ValidationContext contextForChildren = validationContext.withParent(this); isValid = jobConfigs.validateTree(contextForChildren) && isValid; isValid = approval.validateTree(contextForChildren) && isValid; isValid = variables.validateTree(contextForChildren) && isValid; return isValid; } public void validate(ValidationContext validationContext) { isNameValid(); } private boolean isNameValid() { if (!new NameTypeValidator().isNameValid(name)) { this.errors.add(NAME, NameTypeValidator.errorMessage("stage", name)); return false; } return true; } public void validateNameUniqueness(Map<String, StageConfig> stageNameMap) { if (isNameValid()) { String currentName = name.toLower(); StageConfig stageWithSameName = stageNameMap.get(currentName); if (stageWithSameName == null) { stageNameMap.put(currentName, this); } else { stageWithSameName.nameConflictError(); this.nameConflictError(); } } } public ConfigErrors errors() { return errors; } public void addError(String fieldName, String message) { errors.add(fieldName, message); } public void setConfigAttributes(Object attributes) { setConfigAttributes(attributes, null); } public void setConfigAttributes(Object attributes, TaskFactory taskFactory) { if (attributes == null) { return; } Map attributeMap = (Map) attributes; if (attributeMap.containsKey(NAME)) { name = new CaseInsensitiveString((String) attributeMap.get(NAME)); } if (attributeMap.containsKey(ARTIFACT_CLEANUP_PROHIBITED)) { artifactCleanupProhibited = attributeMap.get(ARTIFACT_CLEANUP_PROHIBITED).equals("1") ? true : false; } if (attributeMap.containsKey(FETCH_MATERIALS)) { fetchMaterials = attributeMap.get(FETCH_MATERIALS).equals("1") ? true : false; } if (attributeMap.containsKey(CLEAN_WORKING_DIR)) { cleanWorkingDir = attributeMap.get(CLEAN_WORKING_DIR).equals("1") ? true : false; } if (attributeMap.containsKey(APPROVAL)) { approval.setConfigAttributes(attributeMap.get(APPROVAL)); } if (attributeMap.containsKey(JOBS)) { if (jobConfigs == null) { jobConfigs = new JobConfigs(); } jobConfigs.setConfigAttributes(attributeMap.get(JOBS), taskFactory); } if (attributeMap.containsKey(ENVIRONMENT_VARIABLES)) { variables.setConfigAttributes(attributeMap.get(ENVIRONMENT_VARIABLES)); } if (attributeMap.containsKey(SECURITY_MODE)) { String mode = (String) attributeMap.get(SECURITY_MODE); if ("define".equals(mode)) { approval.setOperatePermissions((List<Map<String, String>>) attributeMap.get(OPERATE_USERS), (List<Map<String, String>>) attributeMap.get(OPERATE_ROLES)); } if ("inherit".equals(mode)) { approval.removeOperatePermissions(); } } } private void nameConflictError() { errors.add(NAME, String.format("You have defined multiple stages called '%s'. Stage names are case-insensitive and must be unique.", name)); } public JobConfigs getJobs() { return jobConfigs; } public void setJobs(JobConfigs jobConfigs) { this.jobConfigs = jobConfigs; } public List<AdminUser> getOperateUsers() { return getApproval().getAuthConfig().getUsers(); } public List<AdminRole> getOperateRoles() { return getApproval().getAuthConfig().getRoles(); } public boolean isArtifactCleanupProhibited() { return artifactCleanupProhibited; } public void setArtifactCleanupProhibited(boolean artifactCleanupProhibited) { this.artifactCleanupProhibited = artifactCleanupProhibited; } public void cleanupAllUsagesOfRole(Role roleToDelete) { this.getApproval().getAuthConfig().remove(new AdminRole(roleToDelete)); } public boolean canBeOperatedBy(Role role) { return getOperateRoles().contains(new AdminRole(role)); } }