Skip to content
Permalink
Browse files

Added pipeline trigger service that handles triggering of a pipeline …

…with various options - #4319 (#4346)
  • Loading branch information...
jyotisingh authored and ketan committed Feb 21, 2018
1 parent 43db6bd commit 666b20667e0e3df1834e7e8a339bd1d527db545b
Showing with 1,495 additions and 133 deletions.
  1. +1 −1 api/api-base/src/main/java/com/thoughtworks/go/api/ControllerMethods.java
  2. +5 −5 api/api-base/src/main/java/com/thoughtworks/go/api/representers/JsonReader.java
  3. +2 −0 api/api-pipeline-operations-v1/build.gradle
  4. +32 −5 ...ain/java/com/thoughtworks/go/apiv1/pipelineoperations/PipelineOperationsControllerV1Delegate.java
  5. +23 −0 ...in/java/com/thoughtworks/go/apiv1/pipelineoperations/exceptions/InvalidGoCipherTextException.java
  6. +38 −0 ...ava/com/thoughtworks/go/apiv1/pipelineoperations/representers/EnvrionmentVariableRepresenter.java
  7. +28 −0 ...n/java/com/thoughtworks/go/apiv1/pipelineoperations/representers/MaterialRevisionRepresenter.java
  8. +43 −0 ...com/thoughtworks/go/apiv1/pipelineoperations/representers/PipelineScheduleOptionsRepresenter.java
  9. +3 −4 ...main/java/com/thoughtworks/go/apiv1/pipelineoperations/spring/PipelineOperationsControllerV1.java
  10. +184 −3 ...vy/com/thoughtworks/go/apiv1/pipelineoperations/PipelineOperationsControllerV1DelegateTest.groovy
  11. +79 −0 ...oughtworks/go/apiv1/pipelineoperations/representers/PipelineScheduleOptionsRepresenterTest.groovy
  12. +5 −3 ...com/thoughtworks/go/apiv1/pipelineselection/representers/PipelineSelectionsRepresenterTest.groovy
  13. +3 −1 .../com/thoughtworks/go/apiv1/serverhealthmessages/ServerHealthMessagesControllerDelegateTest.groovy
  14. +9 −5 common/src/main/java/com/thoughtworks/go/server/service/result/HttpOperationResult.java
  15. +9 −5 common/src/main/java/com/thoughtworks/go/server/service/result/OperationResult.java
  16. +5 −0 common/src/main/java/com/thoughtworks/go/server/service/result/ServerHealthStateOperationResult.java
  17. +10 −6 config/config-api/src/main/java/com/thoughtworks/go/config/EnvironmentVariablesConfig.java
  18. +6 −2 config/config-api/src/main/java/com/thoughtworks/go/config/PipelineConfig.java
  19. +16 −0 config/config-api/src/test/java/com/thoughtworks/go/helper/PartialConfigMother.java
  20. +13 −3 config/config-api/src/test/java/com/thoughtworks/go/helper/PipelineConfigMother.java
  21. +51 −0 server/src/main/java/com/thoughtworks/go/server/domain/MaterialForScheduling.java
  22. +81 −0 server/src/main/java/com/thoughtworks/go/server/domain/PipelineScheduleOptions.java
  23. +30 −18 server/src/main/java/com/thoughtworks/go/server/scheduling/BuildCauseProducerService.java
  24. +8 −0 server/src/main/java/com/thoughtworks/go/server/scheduling/ScheduleOptions.java
  25. +52 −0 server/src/main/java/com/thoughtworks/go/server/service/PipelineTriggerService.java
  26. +147 −0 server/src/main/java/com/thoughtworks/go/server/service/builders/ScheduleOptionsBuilder.java
  27. +5 −0 server/src/main/java/com/thoughtworks/go/server/service/result/DiskSpaceOperationResult.java
  28. +5 −0 ...in/java/com/thoughtworks/go/server/service/result/ServerHealthServiceUpdatingOperationResult.java
  29. +65 −64 server/src/test-fast/java/com/thoughtworks/go/server/scheduling/BuildCauseProducerServiceTest.java
  30. +2 −0 server/src/test-fast/java/com/thoughtworks/go/server/scheduling/ScheduleCheckListenerTest.java
  31. +107 −6 ...integration/java/com/thoughtworks/go/server/service/BuildCauseProducerServiceIntegrationTest.java
  32. +426 −0 ...st-integration/java/com/thoughtworks/go/server/service/PipelineTriggerServiceIntegrationTest.java
  33. +2 −2 server/webapp/WEB-INF/urlrewrite.xml
@@ -95,7 +95,7 @@ default String renderHTTPOperationResult(HttpLocalizedOperationResult result, Re

default String renderHTTPOperationResult(HttpOperationResult result, Request request, Response response) throws IOException {
response.status(result.httpCode());
return writerForTopLevelObject(request, response, writer -> writer.add("message", result.message()));
return writerForTopLevelObject(request, response, writer -> writer.add("message", result.fullMessage()));
}

default String writerForTopLevelObject(Request request, Response response, Consumer<OutputWriter> consumer) throws IOException {
@@ -39,7 +39,7 @@ public JsonReader(JsonObject jsonObject) {

public String getString(String property) {
return optString(property)
.orElseThrow(() -> haltBecauseMissingJsonProperty(property));
.orElseThrow(() -> haltBecauseMissingJsonProperty(property));
}

public Optional<String> optString(String property) {
@@ -88,7 +88,7 @@ public String getString(String property) {

public JsonReader readJsonObject(String property) {
return optJsonObject(property)
.orElseThrow(() -> haltBecauseMissingJsonProperty(property));
.orElseThrow(() -> haltBecauseMissingJsonProperty(property));
}

public void readStringIfPresent(String key, Consumer<String> setterMethod) {
@@ -104,9 +104,9 @@ public void readArrayIfPresent(String key, Consumer<JsonArray> setterMethod) {
try {
Spliterator<JsonElement> iterator = jsonObject.getAsJsonArray(property).spliterator();
return Optional.of(
StreamSupport.stream(iterator, false)
.map(JsonElement::getAsString)
.collect(Collectors.toList()));
StreamSupport.stream(iterator, false)
.map(JsonElement::getAsString)
.collect(Collectors.toList()));
} catch (Exception e) {
throw haltBecausePropertyIsNotAJsonStringArray(property);
}
@@ -26,6 +26,8 @@ dependencies {
compile project(':config:config-api')
compile project(':api:api-base')

compileOnly(group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.47')

testCompile project(path: ':api:api-base', configuration: 'testOutput')
testCompile project(path: ':config:config-api', configuration: 'testOutput')
}
@@ -21,19 +21,23 @@
import com.thoughtworks.go.api.representers.JsonReader;
import com.thoughtworks.go.api.spring.ApiAuthenticationHelper;
import com.thoughtworks.go.api.util.GsonTransformer;
import com.thoughtworks.go.api.util.HaltApiMessages;
import com.thoughtworks.go.api.util.MessageJson;
import com.thoughtworks.go.apiv1.pipelineoperations.exceptions.InvalidGoCipherTextException;
import com.thoughtworks.go.apiv1.pipelineoperations.representers.PipelineScheduleOptionsRepresenter;
import com.thoughtworks.go.apiv1.pipelineoperations.representers.TriggerOptions;
import com.thoughtworks.go.apiv1.pipelineoperations.representers.TriggerWithOptionsViewRepresenter;
import com.thoughtworks.go.config.EnvironmentVariablesConfig;
import com.thoughtworks.go.config.exceptions.RecordNotFoundException;
import com.thoughtworks.go.i18n.Localizer;
import com.thoughtworks.go.presentation.pipelinehistory.PipelineInstanceModel;
import com.thoughtworks.go.server.service.GoConfigService;
import com.thoughtworks.go.server.service.PipelineHistoryService;
import com.thoughtworks.go.server.service.PipelinePauseService;
import com.thoughtworks.go.server.service.PipelineUnlockApiService;
import com.thoughtworks.go.server.domain.PipelineScheduleOptions;
import com.thoughtworks.go.server.service.*;
import com.thoughtworks.go.server.service.result.HttpLocalizedOperationResult;
import com.thoughtworks.go.server.service.result.HttpOperationResult;
import com.thoughtworks.go.spark.Routes;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpStatus;
import spark.Request;
import spark.Response;

@@ -46,13 +50,15 @@
private final ApiAuthenticationHelper apiAuthenticationHelper;
private final Localizer localizer;
private final PipelineUnlockApiService pipelineUnlockApiService;
private PipelineTriggerService pipelineTriggerService;
private GoConfigService goConfigService;
private PipelineHistoryService pipelineHistoryService;

public PipelineOperationsControllerV1Delegate(PipelinePauseService pipelinePauseService, PipelineUnlockApiService pipelineUnlockApiService, ApiAuthenticationHelper apiAuthenticationHelper, Localizer localizer, GoConfigService goConfigService, PipelineHistoryService pipelineHistoryService) {
public PipelineOperationsControllerV1Delegate(PipelinePauseService pipelinePauseService, PipelineUnlockApiService pipelineUnlockApiService, PipelineTriggerService pipelineTriggerService, ApiAuthenticationHelper apiAuthenticationHelper, Localizer localizer, GoConfigService goConfigService, PipelineHistoryService pipelineHistoryService) {
super(ApiVersion.v1);
this.pipelinePauseService = pipelinePauseService;
this.pipelineUnlockApiService = pipelineUnlockApiService;
this.pipelineTriggerService = pipelineTriggerService;
this.apiAuthenticationHelper = apiAuthenticationHelper;
this.localizer = localizer;
this.goConfigService = goConfigService;
@@ -76,13 +82,19 @@ public void setupRoutes() {
before(Routes.Pipeline.UNPAUSE_PATH, mimeType, apiAuthenticationHelper::checkPipelineGroupOperateUserAnd401);
before(Routes.Pipeline.UNLOCK_PATH, mimeType, apiAuthenticationHelper::checkPipelineGroupOperateUserAnd401);
before(Routes.Pipeline.TRIGGER_OPTIONS_PATH, mimeType, apiAuthenticationHelper::checkPipelineGroupOperateUserAnd401);
before(Routes.Pipeline.SCHEDULE_PATH, mimeType, apiAuthenticationHelper::checkPipelineGroupOperateUserAnd401);

post(Routes.Pipeline.PAUSE_PATH, mimeType, this::pause);
post(Routes.Pipeline.UNPAUSE_PATH, mimeType, this::unpause);
post(Routes.Pipeline.UNLOCK_PATH, mimeType, this::unlock);
get(Routes.Pipeline.TRIGGER_OPTIONS_PATH, mimeType, this::triggerOptions);
post(Routes.Pipeline.SCHEDULE_PATH, mimeType, this::schedule);

exception(RecordNotFoundException.class, this::notFound);
exception(InvalidGoCipherTextException.class, (InvalidGoCipherTextException exception, Request request, Response response) -> {
response.status(HttpStatus.INTERNAL_SERVER_ERROR.value());
response.body(MessageJson.create(HaltApiMessages.errorWhileEncryptingMessage()));
});
});
}

@@ -120,4 +132,19 @@ public String triggerOptions(Request request, Response response) throws IOExcept
return writerForTopLevelObject(request, response, writer -> TriggerWithOptionsViewRepresenter.toJSON(writer, triggerOptions));
}

public String schedule(Request req, Response res) throws IOException {
HttpOperationResult result = new HttpOperationResult();
String pipelineName = req.params("pipeline_name");
pipelineTriggerService.schedule(pipelineName, getScheduleOptions(req), currentUsername(), result);
return renderHTTPOperationResult(result, req, res);
}

private PipelineScheduleOptions getScheduleOptions(Request req) {
if (StringUtils.isBlank(req.body())) {
return new PipelineScheduleOptions();
}
GsonTransformer gsonTransformer = GsonTransformer.getInstance();
JsonReader jsonReader = gsonTransformer.jsonReaderFrom(req.body());
return PipelineScheduleOptionsRepresenter.fromJSON(jsonReader);
}
}
@@ -0,0 +1,23 @@
/*
* Copyright 2018 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.apiv1.pipelineoperations.exceptions;

public class InvalidGoCipherTextException extends RuntimeException {
public InvalidGoCipherTextException(String message, Throwable throwable) {
super(message, throwable);
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2018 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.apiv1.pipelineoperations.representers;

import com.thoughtworks.go.api.representers.JsonReader;
import com.thoughtworks.go.apiv1.pipelineoperations.exceptions.InvalidGoCipherTextException;
import com.thoughtworks.go.config.EnvironmentVariableConfig;
import org.bouncycastle.crypto.InvalidCipherTextException;

public class EnvrionmentVariableRepresenter {
public static EnvironmentVariableConfig fromJSON(JsonReader jsonReader) {
String name = jsonReader.getString("name");
Boolean secure = jsonReader.optBoolean("secure").orElse(false);
String value = secure ? jsonReader.optString("value").orElse(null) : jsonReader.getString("value");
String encryptedValue = jsonReader.optString("encrypted_value").orElse(null);
try {
EnvironmentVariableConfig environmentVariableConfig = new EnvironmentVariableConfig();
environmentVariableConfig.deserialize(name, value, secure, encryptedValue);
return environmentVariableConfig;
} catch (InvalidCipherTextException e) {
throw new InvalidGoCipherTextException(e.getMessage(), e);
}
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2018 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.apiv1.pipelineoperations.representers;

import com.thoughtworks.go.api.representers.JsonReader;
import com.thoughtworks.go.server.domain.MaterialForScheduling;

public class MaterialRevisionRepresenter {
public static MaterialForScheduling fromJSON(JsonReader jsonReader) {
String name = jsonReader.getString("fingerprint");
String value = jsonReader.getString("revision");
return new MaterialForScheduling(name, value);
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2018 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.apiv1.pipelineoperations.representers;

import com.thoughtworks.go.api.representers.JsonReader;
import com.thoughtworks.go.config.EnvironmentVariablesConfig;
import com.thoughtworks.go.server.domain.MaterialForScheduling;
import com.thoughtworks.go.server.domain.PipelineScheduleOptions;

import java.util.ArrayList;
import java.util.List;

public class PipelineScheduleOptionsRepresenter {
public static PipelineScheduleOptions fromJSON(JsonReader jsonReader) {
PipelineScheduleOptions model = new PipelineScheduleOptions();
model.shouldPerformMDUBeforeScheduling(jsonReader.optBoolean("update_materials_before_scheduling").orElse(Boolean.TRUE));
jsonReader.readArrayIfPresent("materials", materials -> {
List<MaterialForScheduling> materialsForScheduling = new ArrayList<>();
materials.forEach(material -> materialsForScheduling.add(MaterialRevisionRepresenter.fromJSON(new JsonReader(material.getAsJsonObject()))));
model.setMaterials(materialsForScheduling);
});
jsonReader.readArrayIfPresent("environment_variables", environmentVariables -> {
EnvironmentVariablesConfig variables = new EnvironmentVariablesConfig();
environmentVariables.forEach(variable -> variables.add(EnvrionmentVariableRepresenter.fromJSON(new JsonReader(variable.getAsJsonObject()))));
model.setEnvironmentVariables(variables);
});
return model;
}
}
@@ -19,10 +19,7 @@
import com.thoughtworks.go.api.spring.ApiAuthenticationHelper;
import com.thoughtworks.go.apiv1.pipelineoperations.PipelineOperationsControllerV1Delegate;
import com.thoughtworks.go.i18n.Localizer;
import com.thoughtworks.go.server.service.GoConfigService;
import com.thoughtworks.go.server.service.PipelineHistoryService;
import com.thoughtworks.go.server.service.PipelinePauseService;
import com.thoughtworks.go.server.service.PipelineUnlockApiService;
import com.thoughtworks.go.server.service.*;
import com.thoughtworks.go.spark.spring.SparkSpringController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -33,6 +30,7 @@

@Autowired
public PipelineOperationsControllerV1(PipelinePauseService pipelinePauseService,
PipelineTriggerService pipelineTriggerService,
ApiAuthenticationHelper apiAuthenticationHelper,
Localizer localizer,
PipelineUnlockApiService pipelineUnlockApiService,
@@ -42,6 +40,7 @@ public PipelineOperationsControllerV1(PipelinePauseService pipelinePauseService,
this.delegate = new PipelineOperationsControllerV1Delegate(
pipelinePauseService,
pipelineUnlockApiService,
pipelineTriggerService,
apiAuthenticationHelper,
localizer,
goConfigService,

0 comments on commit 666b206

Please sign in to comment.
You can’t perform that action at this time.