/* * Copyright 2016 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 java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import com.thoughtworks.go.config.remote.ConfigOrigin; import com.thoughtworks.go.config.remote.ConfigReposConfig; import com.thoughtworks.go.domain.ConfigErrors; import com.thoughtworks.go.domain.EnvironmentPipelineMatcher; import com.thoughtworks.go.util.command.EnvironmentVariableContext; import org.apache.commons.lang.builder.ToStringBuilder; import static com.thoughtworks.go.util.command.EnvironmentVariableContext.GO_ENVIRONMENT_NAME; /** * @understands the current persistent information related to a logical grouping of machines */ @ConfigTag("environment") public class BasicEnvironmentConfig implements EnvironmentConfig { @ConfigAttribute(value = NAME_FIELD, optional = false) private CaseInsensitiveString name; @ConfigSubtag private EnvironmentVariablesConfig variables = new EnvironmentVariablesConfig(); @ConfigSubtag private EnvironmentAgentsConfig agents = new EnvironmentAgentsConfig(); @ConfigSubtag private EnvironmentPipelinesConfig pipelines = new EnvironmentPipelinesConfig(); private final ConfigErrors configErrors = new ConfigErrors(); private ConfigOrigin origin; public BasicEnvironmentConfig() { } public BasicEnvironmentConfig(final CaseInsensitiveString name) { this.name = name; } @Override public void validate(ValidationContext validationContext) { // each of these references is defined in this.origin for (EnvironmentPipelineConfig pipelineRefConfig : this.pipelines) { ConfigReposConfig configRepos = validationContext.getConfigRepos(); PipelineConfig pipelineConfig = validationContext.getPipelineConfigByName(pipelineRefConfig.getName()); if (pipelineConfig == null) { continue;//other rule will error that we reference unknown pipeline } if (validationContext.shouldCheckConfigRepo()) { if (!configRepos.isReferenceAllowed(this.origin, pipelineConfig.getOrigin())) pipelineRefConfig.addError(EnvironmentPipelineConfig.ORIGIN, String.format("Environment defined in %s cannot reference a pipeline in %s", this.origin, displayNameFor(pipelineConfig.getOrigin()))); } } } @Override public boolean validateTree(ConfigSaveValidationContext validationContext, CruiseConfig preprocessedConfig) { validate(validationContext); try { validateContainsOnlyPipelines(preprocessedConfig.getAllPipelineNames()); } catch (RuntimeException e) { errors().add("pipeline", e.getMessage()); } validateContainsOnlyUuids(preprocessedConfig.agents().acceptedUuids()); boolean isValid = ErrorCollector.getAllErrors(this).isEmpty(); ValidationContext contextForChildren = validationContext.withParent(this); isValid = isValid && variables.validateTree(contextForChildren); return isValid; } private String displayNameFor(ConfigOrigin origin) { return origin != null ? origin.displayName() : "cruise-config.xml"; } @Override public ConfigErrors errors() { return configErrors; } @Override public void addError(String fieldName, String message) { configErrors.add(fieldName, message); } @Override public EnvironmentPipelineMatcher createMatcher() { return new EnvironmentPipelineMatcher(name, agents.getUuids(), pipelines); } @Override public boolean hasAgent(String uuid) { for (EnvironmentAgentConfig agent : agents) { if (agent.hasUuid(uuid)) { return true; } } return false; } @Override public boolean validateContainsOnlyUuids(Set<String> uuids) { boolean isValid = true; for (EnvironmentAgentConfig agent : agents) { isValid = agent.validateUuidPresent(name, uuids) && isValid; } return isValid; } @Override public boolean containsPipeline(final CaseInsensitiveString pipelineName) { return pipelines.containsPipelineNamed(pipelineName); } @Override public void addAgent(String uuid) { agents.add(new EnvironmentAgentConfig(uuid)); } @Override public void addAgentIfNew(String uuid) { EnvironmentAgentConfig agentConfig = new EnvironmentAgentConfig(uuid); if (!agents.contains(agentConfig)) { agents.add(agentConfig); } } @Override public void removeAgent(String uuid) { agents.remove(new EnvironmentAgentConfig(uuid)); } @Override public boolean hasName(final CaseInsensitiveString environmentName) { return name.equals(environmentName); } @Override public void addPipeline(final CaseInsensitiveString pipelineName) { pipelines.add(new EnvironmentPipelineConfig(pipelineName)); } @Override public void removePipeline(final CaseInsensitiveString pipelineName) { pipelines.remove(new EnvironmentPipelineConfig(pipelineName)); } @Override public boolean contains(String pipelineName) { return pipelines.containsPipelineNamed(new CaseInsensitiveString(pipelineName)); } @Override public void validateContainsOnlyPipelines(List<CaseInsensitiveString> pipelineNames) { pipelines.validateContainsOnlyPipelines(name, pipelineNames); } @Override public boolean hasSamePipelinesAs(EnvironmentConfig other) { for (EnvironmentPipelineConfig pipeline : pipelines) { for (CaseInsensitiveString name : other.getPipelineNames()) { if (name.equals(pipeline.getName())) return true; } } return false; } @Override public CaseInsensitiveString name() { return name; } public void setName(CaseInsensitiveString name) { this.name = name; } @Override public EnvironmentAgentsConfig getAgents() { return agents; } public void setAgents(List<EnvironmentAgentConfig> agents) { this.agents.clear(); this.agents.addAll(agents); } @Override public boolean equals(Object o) { if (this == o) { return true; } EnvironmentConfig that = as(EnvironmentConfig.class, o); if (that == null) return false; if (agents != null ? !agents.equals(that.getAgents()) : that.getAgents() != null) { return false; } if (name != null ? !name.equals(that.name()) : that.name() != null) { return false; } if (pipelines != null ? !pipelines.equals(that.getPipelines()) : that.getPipelines() != null) { return false; } if (variables != null ? !variables.equals(that.getVariables()) : that.getVariables() != null) { return false; } return true; } @Override public int hashCode() { int result = (name != null ? name.hashCode() : 0); result = 31 * result + (agents != null ? agents.hashCode() : 0); result = 31 * result + (pipelines != null ? pipelines.hashCode() : 0); result = 31 * result + (variables != null ? variables.hashCode() : 0); return result; } private static <T> T as(Class<T> clazz, Object o) { if (clazz.isInstance(o)) { return clazz.cast(o); } return null; } @Override public String toString() { return ToStringBuilder.reflectionToString(this); } @Override public void addEnvironmentVariable(String name, String value) { variables.add(new EnvironmentVariableConfig(name.trim(), value)); } @Override public void addEnvironmentVariable(EnvironmentVariableConfig variableConfig) { variables.add(variableConfig); } @Override public EnvironmentVariableContext createEnvironmentContext() { EnvironmentVariableContext context = new EnvironmentVariableContext( GO_ENVIRONMENT_NAME, CaseInsensitiveString.str(name)); variables.addTo(context); return context; } @Override public List<CaseInsensitiveString> getPipelineNames() { ArrayList<CaseInsensitiveString> pipelineNames = new ArrayList<>(); for (EnvironmentPipelineConfig pipeline : pipelines) { pipelineNames.add(pipeline.getName()); } return pipelineNames; } @Override public EnvironmentPipelinesConfig getPipelines() { return pipelines; } public void setPipelines(List<EnvironmentPipelineConfig> pipelines) { this.pipelines.clear(); this.pipelines.addAll(pipelines); } @Override public boolean hasVariable(String variableName) { return variables.hasVariable(variableName); } @Override public EnvironmentVariablesConfig getVariables() { return variables; } public void setVariables(EnvironmentVariablesConfig environmentVariables) { this.variables = environmentVariables; } @Override public void setConfigAttributes(Object attributes) { if (attributes == null) { return; } Map attributeMap = (Map) attributes; if (attributeMap.containsKey(NAME_FIELD)) { name = new CaseInsensitiveString((String) attributeMap.get(NAME_FIELD)); } if (attributeMap.containsKey(PIPELINES_FIELD)) { pipelines.setConfigAttributes(attributeMap.get(PIPELINES_FIELD)); } if (attributeMap.containsKey(AGENTS_FIELD)) { agents.setConfigAttributes(attributeMap.get(AGENTS_FIELD)); } if (attributeMap.containsKey(VARIABLES_FIELD)) { variables.setConfigAttributes(attributeMap.get(VARIABLES_FIELD)); } } @Override public EnvironmentVariablesConfig getPlainTextVariables() { return variables.getPlainTextVariables(); } @Override public EnvironmentVariablesConfig getSecureVariables() { return variables.getSecureVariables(); } @Override public EnvironmentConfig getLocal() { if (this.isLocal()) return this; else return null; } @Override public ConfigOrigin getOrigin() { return origin; } @Override public void setOrigins(ConfigOrigin origins) { this.origin = origins; for (EnvironmentVariableConfig environmentVariableConfig : this.variables) { environmentVariableConfig.setOrigins(origins); } } @Override public EnvironmentPipelinesConfig getRemotePipelines() { if (this.isLocal()) return new EnvironmentPipelinesConfig(); else return this.pipelines; } @Override public EnvironmentAgentsConfig getLocalAgents() { if (this.isLocal()) return this.agents; else return new EnvironmentAgentsConfig(); } public boolean isLocal() { return this.origin == null || this.origin.isLocal(); } @Override public boolean isEnvironmentEmpty() { return this.variables.isEmpty() && this.agents.isEmpty() && this.pipelines.isEmpty(); } @Override public boolean containsPipelineRemotely(CaseInsensitiveString pipelineName) { if (this.isLocal()) { return false; } if (!this.containsPipeline(pipelineName)) { return false; } return true; } @Override public boolean containsAgentRemotely(String uuid) { if (this.isLocal()) { return false; } if (!this.hasAgent(uuid)) { return false; } return true; } @Override public boolean containsEnvironmentVariableRemotely(String variableName) { if (this.isLocal()) { return false; } if (!this.getVariables().hasVariable(variableName)) { return false; } return true; } }