/* * 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.update; import com.thoughtworks.go.config.*; import com.thoughtworks.go.config.commands.EntityConfigUpdateCommand; import com.thoughtworks.go.config.merge.MergeEnvironmentConfig; import com.thoughtworks.go.i18n.Localizable; import com.thoughtworks.go.i18n.LocalizedMessage; import com.thoughtworks.go.server.domain.Username; import com.thoughtworks.go.server.service.GoConfigService; import com.thoughtworks.go.server.service.result.HttpLocalizedOperationResult; import com.thoughtworks.go.serverhealth.HealthStateType; import java.util.List; public class PatchEnvironmentCommand extends EnvironmentCommand implements EntityConfigUpdateCommand<EnvironmentConfig> { private final GoConfigService goConfigService; private final EnvironmentConfig environmentConfig; private final List<String> pipelinesToAdd; private final List<String> pipelinesToRemove; private final List<String> agentsToAdd; private final List<String> agentsToRemove; private final List<EnvironmentVariableConfig> envVarsToAdd; private final List<String> envVarsToRemove; private final Username username; private final Localizable.CurryableLocalizable actionFailed; private final HttpLocalizedOperationResult result; public PatchEnvironmentCommand(GoConfigService goConfigService, EnvironmentConfig environmentConfig, List<String> pipelinesToAdd, List<String> pipelinesToRemove, List<String> agentsToAdd, List<String> agentsToRemove, List<EnvironmentVariableConfig> envVarsToAdd, List<String> envVarsToRemove, Username username, Localizable.CurryableLocalizable actionFailed, HttpLocalizedOperationResult result) { super(actionFailed, environmentConfig, result); this.goConfigService = goConfigService; this.environmentConfig = environmentConfig; this.pipelinesToAdd = pipelinesToAdd; this.pipelinesToRemove = pipelinesToRemove; this.agentsToAdd = agentsToAdd; this.agentsToRemove = agentsToRemove; this.envVarsToAdd = envVarsToAdd; this.envVarsToRemove = envVarsToRemove; this.username = username; this.actionFailed = actionFailed; this.result = result; } @Override public void update(CruiseConfig configForEdit) throws Exception { EnvironmentConfig environmentConfig = configForEdit.getEnvironments().named(this.environmentConfig.name()); for (String uuid : agentsToAdd) { environmentConfig.addAgent(uuid); } for (String uuid : agentsToRemove) { environmentConfig.removeAgent(uuid); } for (String pipelineName : pipelinesToAdd) { environmentConfig.addPipeline(new CaseInsensitiveString(pipelineName)); } for (String pipelineName : pipelinesToRemove) { environmentConfig.removePipeline(new CaseInsensitiveString(pipelineName)); } for (EnvironmentVariableConfig variableConfig : envVarsToAdd) { environmentConfig.addEnvironmentVariable(variableConfig); } for (String variableName : envVarsToRemove) { environmentConfig.getVariables().removeIfExists(variableName); } } @Override public boolean isValid(CruiseConfig preprocessedConfig) { EnvironmentConfig preprocessedEnvironmentConfig = preprocessedConfig.getEnvironments().find(environmentConfig.name()); boolean isValid = validateRemovalOfInvalidEntities(); if (preprocessedEnvironmentConfig instanceof MergeEnvironmentConfig) { isValid = validateRemovalOfRemoteEntities(preprocessedEnvironmentConfig); } return isValid && super.isValid(preprocessedConfig); } private boolean validateRemovalOfRemotePipelines(EnvironmentConfig preprocessedEnvironmentConfig) { for (String pipelineToRemove : pipelinesToRemove) { if (preprocessedEnvironmentConfig.containsPipelineRemotely(new CaseInsensitiveString(pipelineToRemove))) { String origin = ((MergeEnvironmentConfig) preprocessedEnvironmentConfig).getOriginForPipeline(new CaseInsensitiveString(pipelineToRemove)).displayName(); String message = String.format("Pipeline '%s' cannot be removed from environment '%s' as the association has been defined remotely in [%s]", pipelineToRemove, environmentConfig.name(), origin); result.unprocessableEntity(actionFailed.addParam(message)); return false; } } return true; } private boolean validateRemovalOfRemoteAgents(EnvironmentConfig preprocessedEnvironmentConfig) { for (String agentToRemove : agentsToRemove) { if (preprocessedEnvironmentConfig.containsAgentRemotely(agentToRemove)) { String origin = ((MergeEnvironmentConfig) preprocessedEnvironmentConfig).getOriginForAgent(agentToRemove).displayName(); String message = String.format("Agent with uuid '%s' cannot be removed from environment '%s' as the association has been defined remotely in [%s]", agentToRemove, environmentConfig.name(), origin); result.unprocessableEntity(actionFailed.addParam(message)); return false; } } return true; } private boolean validateRemovalOfEnvironmentVariables(EnvironmentConfig preprocessedEnvironmentConfig) { for (String variableName : envVarsToRemove) { if (preprocessedEnvironmentConfig.containsEnvironmentVariableRemotely(variableName)) { String origin = ((MergeEnvironmentConfig) preprocessedEnvironmentConfig).getOriginForEnvironmentVariable(variableName).displayName(); String message = String.format("Environment variable with name '%s' cannot be removed from environment '%s' as the association has been defined remotely in [%s]", variableName, environmentConfig.name(), origin); result.unprocessableEntity(actionFailed.addParam(message)); return false; } } return true; } private boolean validateRemovalOfRemoteEntities(EnvironmentConfig preprocessedEnvironmentConfig) { boolean isValid = validateRemovalOfRemotePipelines(preprocessedEnvironmentConfig); isValid = isValid && validateRemovalOfRemoteAgents(preprocessedEnvironmentConfig); isValid = isValid && validateRemovalOfEnvironmentVariables(preprocessedEnvironmentConfig); return isValid; } private boolean validateRemovalOfInvalidAgents() { EnvironmentConfig environmentConfig = this.environmentConfig; for (String agentToRemove : agentsToRemove) { if (!environmentConfig.hasAgent(agentToRemove)) { String message = String.format("Agent with uuid '%s' does not exist in environment '%s'", agentToRemove, environmentConfig.name()); result.unprocessableEntity(actionFailed.addParam(message)); return false; } } return true; } private boolean validateRemovalOfInvalidPipelines() { EnvironmentConfig environmentConfig = this.environmentConfig; for (String pipelineToRemove : pipelinesToRemove) { if (!environmentConfig.containsPipeline(new CaseInsensitiveString(pipelineToRemove))) { String message = String.format("Pipeline '%s' does not exist in environment '%s'", pipelineToRemove, environmentConfig.name()); result.unprocessableEntity(actionFailed.addParam(message)); return false; } } return true; } private boolean validateRemovalOfInvalidEnvironmentVariable() { EnvironmentConfig environmentConfig = this.environmentConfig; for (String variableName : envVarsToRemove) { if (!environmentConfig.getVariables().hasVariable(variableName)) { String message = String.format("Environment variable with name '%s' does not exist in environment '%s'", variableName, environmentConfig.name()); result.unprocessableEntity(actionFailed.addParam(message)); return false; } } return true; } private boolean validateRemovalOfInvalidEntities() { boolean isValid = validateRemovalOfInvalidPipelines(); isValid = isValid && validateRemovalOfInvalidAgents(); isValid = isValid && validateRemovalOfInvalidEnvironmentVariable(); return isValid; } @Override public void clearErrors() { BasicCruiseConfig.clearErrors(environmentConfig); } @Override public boolean canContinue(CruiseConfig cruiseConfig) { if (!goConfigService.isAdministrator(username.getUsername())) { Localizable noPermission = LocalizedMessage.string("NO_PERMISSION_TO_UPDATE_ENVIRONMENT", environmentConfig.name().toString(), username.getDisplayName()); result.unauthorized(noPermission, HealthStateType.unauthorised()); return false; } return true; } }