Skip to content

Commit

Permalink
Spark implementation of Materials API (#6324)
Browse files Browse the repository at this point in the history
  • Loading branch information
akshaydewan committed Jun 13, 2019
1 parent 8618d15 commit 4d47d86
Show file tree
Hide file tree
Showing 47 changed files with 2,489 additions and 5 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Expand Up @@ -403,3 +403,7 @@ api/api-scms-v1/config/
api/api-scms-v1/logs/
api/api-scms-v1/out/
api/api-scms-v1/target/
api/api-materials-v1/out/
api/api-materials-v1/target/
api/api-materials-v1/logs/
api/api-materials-v1/config/
Expand Up @@ -13,15 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.thoughtworks.go.apiv1.stageoperations.representers;
package com.thoughtworks.go.api.representers;

import com.thoughtworks.go.api.base.OutputWriter;
import com.thoughtworks.go.server.util.Pagination;

import java.util.function.Consumer;

public class PaginationRepresenter {
public static void toJSON(OutputWriter jsonWriter, Pagination pagination) {
jsonWriter.add("page_size", pagination.getPageSize())
.add("offset", pagination.getOffset())
.add("total", pagination.getTotal());
}

public static Consumer<OutputWriter> toJSON(Pagination pagination) {
return outputWriter -> PaginationRepresenter.toJSON(outputWriter, pagination);
}
}
Expand Up @@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.thoughtworks.go.apiv1.stageoperations.representers

package com.thoughtworks.go.api.representers

import com.thoughtworks.go.server.util.Pagination
import org.junit.jupiter.api.Test
Expand All @@ -27,7 +28,7 @@ class PaginationRepresenterTest {
void 'should represent pagination with hal'() {
def pagination = new Pagination(1, 20, 10)

def actualJson = toObjectString({PaginationRepresenter.toJSON(it, pagination) })
def actualJson = toObjectString({ PaginationRepresenter.toJSON(it, pagination) })

assertThatJson(actualJson).isEqualTo(paginationHash)
}
Expand Down
Expand Up @@ -25,7 +25,7 @@ public class ModificationRepresenter {
public static void toJSON(OutputWriter jsonOutputWriter, Modification model, Material material) {
jsonOutputWriter
.addLinks(linksWriter -> {
linksWriter.addLink("vsm", Routes.Materials.vsm(material.getFingerprint(), model.getRevision()));
linksWriter.addLink("vsm", Routes.MaterialConfig.vsm(material.getFingerprint(), model.getRevision()));
})
.addIfNotNull("user_name", model.getUserName())
.addIfNotNull("email_address", model.getEmailAddress())
Expand Down
27 changes: 27 additions & 0 deletions api/api-materials-v1/build.gradle
@@ -0,0 +1,27 @@
/*
* Copyright 2019 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
}
@@ -0,0 +1,74 @@
/*
* Copyright 2019 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.materials;

import com.thoughtworks.go.api.ApiController;
import com.thoughtworks.go.api.ApiVersion;
import com.thoughtworks.go.api.spring.ApiAuthenticationHelper;
import com.thoughtworks.go.apiv1.materials.representers.MaterialConfigsRepresenter;
import com.thoughtworks.go.config.exceptions.HttpException;
import com.thoughtworks.go.config.materials.MaterialConfigs;
import com.thoughtworks.go.server.service.MaterialConfigService;
import com.thoughtworks.go.server.service.MaterialService;
import com.thoughtworks.go.spark.Routes;
import com.thoughtworks.go.spark.spring.SparkSpringController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import spark.Request;
import spark.Response;

import java.io.IOException;

import static spark.Spark.*;

@Component
public class MaterialConfigControllerV1 extends ApiController implements SparkSpringController {

private final ApiAuthenticationHelper apiAuthenticationHelper;
private final MaterialConfigService materialConfigService;

@Autowired
public MaterialConfigControllerV1(ApiAuthenticationHelper apiAuthenticationHelper, MaterialConfigService materialConfigService) {
super(ApiVersion.v1);
this.apiAuthenticationHelper = apiAuthenticationHelper;
this.materialConfigService = materialConfigService;
}

@Override
public String controllerBasePath() {
return Routes.MaterialConfig.BASE;
}

@Override
public void setupRoutes() {
path(controllerBasePath(), () -> {
before("", mimeType, this::setContentType);
before("/*", mimeType, this::setContentType);
before("", mimeType, this::verifyContentType);
before("/*", mimeType, this::verifyContentType);
before("", this.mimeType, this.apiAuthenticationHelper::checkUserAnd403);
before("/*", this.mimeType, this.apiAuthenticationHelper::checkUserAnd403);
get("", mimeType, this::index);
exception(HttpException.class, this::httpException);
});
}

public String index(Request req, Response res) throws IOException {
MaterialConfigs materialConfigs = materialConfigService.getMaterialConfigs(currentUsernameString());
return writerForTopLevelObject(req, res, writer -> MaterialConfigsRepresenter.toJSON(writer, materialConfigs));
}
}
@@ -0,0 +1,93 @@
/*
* Copyright 2019 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.materials;

import com.thoughtworks.go.api.ApiController;
import com.thoughtworks.go.api.ApiVersion;
import com.thoughtworks.go.api.spring.ApiAuthenticationHelper;
import com.thoughtworks.go.apiv1.materials.representers.MaterialConfigsRepresenter;
import com.thoughtworks.go.apiv1.materials.representers.ModificationsRepresenter;
import com.thoughtworks.go.config.exceptions.HttpException;
import com.thoughtworks.go.config.materials.MaterialConfigs;
import com.thoughtworks.go.domain.materials.MaterialConfig;
import com.thoughtworks.go.domain.materials.Modifications;
import com.thoughtworks.go.server.service.MaterialConfigService;
import com.thoughtworks.go.server.service.MaterialService;
import com.thoughtworks.go.server.service.result.HttpOperationResult;
import com.thoughtworks.go.server.util.Pagination;
import com.thoughtworks.go.spark.Routes;
import com.thoughtworks.go.spark.spring.SparkSpringController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import spark.Request;
import spark.Response;

import java.io.IOException;

import static spark.Spark.*;

@Component
public class MaterialModificationsControllerV1 extends ApiController implements SparkSpringController {

private final ApiAuthenticationHelper apiAuthenticationHelper;
private final MaterialConfigService materialConfigService;
private final MaterialService materialService;

@Autowired
public MaterialModificationsControllerV1(ApiAuthenticationHelper apiAuthenticationHelper, MaterialConfigService materialConfigService,
MaterialService materialService) {
super(ApiVersion.v1);
this.apiAuthenticationHelper = apiAuthenticationHelper;
this.materialConfigService = materialConfigService;
this.materialService = materialService;
}

@Override
public String controllerBasePath() {
return Routes.MaterialModifications.BASE;
}

@Override
public void setupRoutes() {
path(controllerBasePath(), () -> {
before("", mimeType, this::setContentType);
before("/*", mimeType, this::setContentType);
before("", mimeType, this::verifyContentType);
before("/*", mimeType, this::verifyContentType);
before("", this.mimeType, this.apiAuthenticationHelper::checkUserAnd403);
before("/*", this.mimeType, this.apiAuthenticationHelper::checkUserAnd403);
get("", mimeType, this::modifications);
get(Routes.MaterialModifications.OFFSET, mimeType, this::modifications);
exception(HttpException.class, this::httpException);
});
}

public String modifications(Request req, Response res) throws IOException {
String fingerprint = req.params("fingerprint");
Integer offset = req.params("offset") == null ? null : Integer.parseInt(req.params("offset"));
HttpOperationResult result = new HttpOperationResult();
MaterialConfig materialConfig = materialConfigService.getMaterialConfig(currentUsernameString(), fingerprint, result);
if (result.canContinue()) {
Long modificationsCount = materialService.getTotalModificationsFor(materialConfig);
Pagination pagination = Pagination.pageStartingAt(offset, modificationsCount.intValue(), 10);
Modifications modifications = materialService.getModificationsFor(materialConfig, pagination);
return writerForTopLevelObject(req, res, writer -> ModificationsRepresenter.toJSON(writer, modifications, pagination, fingerprint));
} else {
return renderHTTPOperationResult(result, req, res);
}
}
}
@@ -0,0 +1,113 @@
/*
* Copyright 2019 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.materials;

import com.thoughtworks.go.api.ApiController;
import com.thoughtworks.go.api.ApiVersion;
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.config.exceptions.HttpException;
import com.thoughtworks.go.server.materials.MaterialUpdateService;
import com.thoughtworks.go.server.service.result.HttpLocalizedOperationResult;
import com.thoughtworks.go.spark.Routes;
import com.thoughtworks.go.spark.spring.SparkSpringController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import spark.Request;
import spark.Response;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static spark.Spark.*;

@Component
public class MaterialNotifyControllerV1 extends ApiController implements SparkSpringController {

private final ApiAuthenticationHelper apiAuthenticationHelper;
private final MaterialUpdateService materialUpdateService;

@Autowired
public MaterialNotifyControllerV1(ApiAuthenticationHelper apiAuthenticationHelper, MaterialUpdateService materialUpdateService) {
super(ApiVersion.v1);
this.apiAuthenticationHelper = apiAuthenticationHelper;
this.materialUpdateService = materialUpdateService;
}

@Override
public String controllerBasePath() {
return Routes.MaterialNotify.BASE;
}

@Override
public void setupRoutes() {
path(controllerBasePath(), () -> {
before("", mimeType, this::setContentType);
before("/*", mimeType, this::setContentType);
before("", mimeType, this::verifyContentType);
before("/*", mimeType, this::verifyContentType);
before("", this.mimeType, this.apiAuthenticationHelper::checkAdminUserAnd403);
before("/*", this.mimeType, this.apiAuthenticationHelper::checkAdminUserAnd403);
post(Routes.MaterialNotify.SVN, mimeType, this::svnNotify);
post(Routes.MaterialNotify.GIT, mimeType, this::gitNotify);
post(Routes.MaterialNotify.HG, mimeType, this::hgNotify);
post(Routes.MaterialNotify.SCM, mimeType, this::scmNotify);
exception(HttpException.class, this::httpException);
});
}

public String svnNotify(Request req, Response res) throws IOException {
return notifyWithRepoUrl(req, res, "svn");
}

public String gitNotify(Request req, Response res) throws IOException {
return notifyWithRepoUrl(req, res, "git");
}

public String hgNotify(Request req, Response res) throws IOException {
return notifyWithRepoUrl(req, res, "hg");
}

public String scmNotify(Request req, Response res) throws IOException {
JsonReader jsonReader = GsonTransformer.getInstance().jsonReaderFrom(req.body());
String repoUrl = jsonReader.getString("scm_name");
return notify(req, res, "scm", "scm_name", repoUrl);
}

private String notifyWithRepoUrl(Request req, Response res, String materialType) throws IOException {
String repoUrl = getRepoUrl(req);
return notify(req, res, materialType, "repository_url", repoUrl);
}

private String notify(Request req, Response res, String materialType, String paramName, String paramValue) throws IOException {
Map<String, String> params = new HashMap<>();
params.put(MaterialUpdateService.TYPE, materialType);
params.put(paramName, paramValue);

HttpLocalizedOperationResult result = new HttpLocalizedOperationResult();
materialUpdateService.notifyMaterialsForUpdate(currentUsername(), params, result);

return renderHTTPOperationResult(result, req, res);
}

private String getRepoUrl(Request req) {
JsonReader jsonReader = GsonTransformer.getInstance().jsonReaderFrom(req.body());
return jsonReader.getString("repository_url");
}
}

0 comments on commit 4d47d86

Please sign in to comment.