diff --git a/.gitignore b/.gitignore index a8dc659bbcb..29c8f951539 100644 --- a/.gitignore +++ b/.gitignore @@ -517,3 +517,7 @@ api/api-compare-v2/out/ api/api-compare-v2/target/ api/api-compare-v2/logs/ api/api-compare-v2/config/ +api/api-internal-dependency-pipelines-v1/out/ +api/api-internal-dependency-pipelines-v1/target/ +api/api-internal-dependency-pipelines-v1/logs/ +api/api-internal-dependency-pipelines-v1/config/ diff --git a/api/api-internal-dependency-pipelines-v1/build.gradle b/api/api-internal-dependency-pipelines-v1/build.gradle new file mode 100644 index 00000000000..dbc603958fe --- /dev/null +++ b/api/api-internal-dependency-pipelines-v1/build.gradle @@ -0,0 +1,27 @@ +/* + * Copyright 2020 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. + */ + +apply plugin: 'jacoco' +apply plugin: 'groovy' + +dependencies { + compile project(':api:api-base') + + testCompile project(path: ':api:api-base', configuration: 'testOutput') + + testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: project.versions.junit5 + testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: project.versions.junit5 +} diff --git a/api/api-internal-dependency-pipelines-v1/src/main/java/com/thoughtworks/go/apiv1/internaldependencypipelines/InternalDependencyPipelinesControllerV1.java b/api/api-internal-dependency-pipelines-v1/src/main/java/com/thoughtworks/go/apiv1/internaldependencypipelines/InternalDependencyPipelinesControllerV1.java new file mode 100644 index 00000000000..d11e8998d34 --- /dev/null +++ b/api/api-internal-dependency-pipelines-v1/src/main/java/com/thoughtworks/go/apiv1/internaldependencypipelines/InternalDependencyPipelinesControllerV1.java @@ -0,0 +1,87 @@ +/* + * Copyright 2020 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.internaldependencypipelines; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.thoughtworks.go.api.ApiController; +import com.thoughtworks.go.api.ApiVersion; +import com.thoughtworks.go.api.spring.ApiAuthenticationHelper; +import com.thoughtworks.go.config.CaseInsensitiveString; +import com.thoughtworks.go.config.CruiseConfig; +import com.thoughtworks.go.server.presentation.FetchArtifactViewHelper; +import com.thoughtworks.go.server.service.GoConfigService; +import com.thoughtworks.go.spark.Routes; +import com.thoughtworks.go.spark.spring.SparkSpringController; +import com.thoughtworks.go.util.SystemEnvironment; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import spark.Request; +import spark.Response; + +import static spark.Spark.*; + +@Component +public class InternalDependencyPipelinesControllerV1 extends ApiController implements SparkSpringController { + + private final ApiAuthenticationHelper apiAuthenticationHelper; + private SystemEnvironment systemEnvironment; + private GoConfigService goConfigService; + private Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls().create(); + + @Autowired + public InternalDependencyPipelinesControllerV1(ApiAuthenticationHelper apiAuthenticationHelper, + SystemEnvironment systemEnvironment, + GoConfigService goConfigService) { + super(ApiVersion.v1); + this.apiAuthenticationHelper = apiAuthenticationHelper; + this.systemEnvironment = systemEnvironment; + this.goConfigService = goConfigService; + } + + @Override + public String controllerBasePath() { + return Routes.InternalDependencyPipelines.BASE; + } + + @Override + public void setupRoutes() { + path(controllerBasePath(), () -> { + before("", mimeType, this::setContentType); + before("/*", mimeType, this::setContentType); + + before("", mimeType, this::verifyContentType); + before("/*", mimeType, this::verifyContentType); + + before("", mimeType, apiAuthenticationHelper::checkUserAnd403); + + get("", mimeType, this::index); + }); + } + + public String index(Request request, Response response) { + String pipelineName = request.params("pipeline_name"); + String stageName = request.params("stage_name"); + + CruiseConfig config = goConfigService.getMergedConfigForEditing(); + FetchArtifactViewHelper helper = new FetchArtifactViewHelper(systemEnvironment, config, new CaseInsensitiveString(pipelineName), new CaseInsensitiveString(stageName), false); + + response.type("application/json"); + return gson.toJson(helper.autosuggestMap()); + } + +} diff --git a/api/api-internal-dependency-pipelines-v1/src/test/groovy/com/thoughtworks/go/apiv1/internaldependencypipelines/InternalDependencyPipelinesControllerV1Test.groovy b/api/api-internal-dependency-pipelines-v1/src/test/groovy/com/thoughtworks/go/apiv1/internaldependencypipelines/InternalDependencyPipelinesControllerV1Test.groovy new file mode 100644 index 00000000000..c73581373fb --- /dev/null +++ b/api/api-internal-dependency-pipelines-v1/src/test/groovy/com/thoughtworks/go/apiv1/internaldependencypipelines/InternalDependencyPipelinesControllerV1Test.groovy @@ -0,0 +1,90 @@ +/* + * Copyright 2020 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.internaldependencypipelines + +import com.thoughtworks.go.api.SecurityTestTrait +import com.thoughtworks.go.api.spring.ApiAuthenticationHelper +import com.thoughtworks.go.config.BasicCruiseConfig +import com.thoughtworks.go.helper.PipelineConfigMother +import com.thoughtworks.go.server.service.GoConfigService +import com.thoughtworks.go.spark.ControllerTrait +import com.thoughtworks.go.spark.NormalUserSecurity +import com.thoughtworks.go.spark.SecurityServiceTrait +import com.thoughtworks.go.util.SystemEnvironment +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.mockito.Mock + +import static org.mockito.Mockito.when +import static org.mockito.MockitoAnnotations.initMocks + +class InternalDependencyPipelinesControllerV1Test implements SecurityServiceTrait, ControllerTrait { + @Mock + GoConfigService goConfigService + + @BeforeEach + void setUp() { + initMocks(this) + } + + @Override + InternalDependencyPipelinesControllerV1 createControllerInstance() { + new InternalDependencyPipelinesControllerV1(new ApiAuthenticationHelper(securityService, goConfigService), new SystemEnvironment(), goConfigService) + } + + @Nested + class Index { + @Nested + class Security implements SecurityTestTrait, NormalUserSecurity { + + @Override + String getControllerMethodUnderTest() { + return "index" + } + + @Override + void makeHttpCall() { + getWithApiHeader(path('pipeline', 'stage')) + } + } + } + + @Test + void 'should return pipeline auto suggestions'() { + def config = new BasicCruiseConfig() + config.addPipeline("first", PipelineConfigMother.pipelineConfig("pipeline1")) + when(goConfigService.getMergedConfigForEditing()).thenReturn(config) + + getWithApiHeader(path('pipeline1', 'stage')) + + assertThatResponse() + .isOk() + .hasJsonBody('{' + + ' "pipeline1": {' + + ' "mingle": {}' + + ' },' + + ' "": {' + + ' "mingle": {}' + + ' }' + + '}') + } + + String path(String name, String stageName) { + return controller.controllerBasePath().replaceAll(":pipeline_name", name).replaceAll(':stage_name', stageName) + } +} diff --git a/server/src/main/resources/applicationContext-global.xml b/server/src/main/resources/applicationContext-global.xml index c929888dba2..f8ade658519 100644 --- a/server/src/main/resources/applicationContext-global.xml +++ b/server/src/main/resources/applicationContext-global.xml @@ -25,6 +25,7 @@ + diff --git a/server/src/main/webapp/WEB-INF/urlrewrite.xml b/server/src/main/webapp/WEB-INF/urlrewrite.xml index f229ba5b5fd..48b86b3d6bc 100644 --- a/server/src/main/webapp/WEB-INF/urlrewrite.xml +++ b/server/src/main/webapp/WEB-INF/urlrewrite.xml @@ -23,6 +23,12 @@ --> + + Internal Dependency Pipelines API + ^/api/internal/pipelines/([^/]+)/([^/]+)/upstream(/?)$ + /spark/api/internal/pipelines/${escape:$1}/${escape:$2}/upstream + + Clicky pipeline config SPA ^/admin/pipelines/([^/]+)/edit(/?)$ diff --git a/settings.gradle b/settings.gradle index 533304d3658..39caab8e9d6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -58,6 +58,7 @@ include ':api:api-export-v1' include ':api:api-feature-toggles-v1' include ':api:api-feeds-api-v1' include ':api:api-internal-command-snippets-v1' +include ':api:api-internal-dependency-pipelines-v1' include ':api:api-internal-environments-v1' include ':api:api-internal-material-test-v1' include ':api:api-internal-pipeline-structure-v1' diff --git a/spark/spark-base/src/main/java/com/thoughtworks/go/spark/Routes.java b/spark/spark-base/src/main/java/com/thoughtworks/go/spark/Routes.java index 131b6788ada..0a9af204c73 100644 --- a/spark/spark-base/src/main/java/com/thoughtworks/go/spark/Routes.java +++ b/spark/spark-base/src/main/java/com/thoughtworks/go/spark/Routes.java @@ -889,4 +889,8 @@ public static class Permissions { public static final String BASE = "/api/auth/permissions"; public static final String DOC = apiDocsUrl("permissions"); } + + public class InternalDependencyPipelines { + public static final String BASE = "/api/internal/pipelines/:pipeline_name/:stage_name/upstream"; + } }