Skip to content

Commit

Permalink
Migrated Package Definition API(V1) to spark:
Browse files Browse the repository at this point in the history
  - Added Index call and CRUD calls.
  • Loading branch information
imvirajp committed Oct 18, 2019
1 parent 8c89ab4 commit fb04833
Show file tree
Hide file tree
Showing 14 changed files with 1,005 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Expand Up @@ -452,3 +452,7 @@ api/api-compare-v1/out/
api/api-compare-v1/target/
api/api-compare-v1/logs/
api/api-compare-v1/config/
api/api-packages-v1/out/
api/api-packages-v1/target/
api/api-packages-v1/logs/
api/api-packages-v1/config/
27 changes: 27 additions & 0 deletions api/api-packages-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,163 @@
/*
* 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.packages;

import com.thoughtworks.go.api.ApiController;
import com.thoughtworks.go.api.ApiVersion;
import com.thoughtworks.go.api.CrudController;
import com.thoughtworks.go.api.base.OutputWriter;
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.apiv1.packages.representers.PackageDefinitionRepresenter;
import com.thoughtworks.go.apiv1.packages.representers.PackageDefinitionsRepresenter;
import com.thoughtworks.go.config.exceptions.EntityType;
import com.thoughtworks.go.domain.packagerepository.PackageDefinition;
import com.thoughtworks.go.server.service.EntityHashingService;
import com.thoughtworks.go.server.service.materials.PackageDefinitionService;
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.List;
import java.util.function.Consumer;

import static com.thoughtworks.go.api.util.HaltApiResponses.haltBecauseEtagDoesNotMatch;
import static spark.Spark.*;

@Component
public class PackagesControllerV1 extends ApiController implements SparkSpringController, CrudController<PackageDefinition> {

private final ApiAuthenticationHelper apiAuthenticationHelper;
private final EntityHashingService entityHashingService;
private final PackageDefinitionService packageDefinitionService;

@Autowired
public PackagesControllerV1(ApiAuthenticationHelper apiAuthenticationHelper, EntityHashingService entityHashingService,
PackageDefinitionService packageDefinitionService) {
super(ApiVersion.v1);
this.apiAuthenticationHelper = apiAuthenticationHelper;
this.entityHashingService = entityHashingService;
this.packageDefinitionService = packageDefinitionService;
}

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

@Override
public void setupRoutes() {
path(controllerBasePath(), () -> {
before("", mimeType, this::setContentType);
before("/*", mimeType, this::setContentType);
before("", mimeType, this.apiAuthenticationHelper::checkAdminUserOrGroupAdminUserAnd403);
before("/*", mimeType, this.apiAuthenticationHelper::checkAdminUserOrGroupAdminUserAnd403);

get("", mimeType, this::index);
get(Routes.Packages.SHOW, mimeType, this::show);
post("", mimeType, this::create);
put(Routes.Packages.SHOW, mimeType, this::update);
delete(Routes.Packages.SHOW, mimeType, this::remove);
});
}

String index(Request request, Response response) throws IOException {
List<PackageDefinition> packages = packageDefinitionService.getPackages();
return writerForTopLevelObject(request, response, outputWriter -> PackageDefinitionsRepresenter.toJSON(outputWriter, packages));
}

String show(Request request, Response response) throws IOException {
String packageId = request.params("package_id");

PackageDefinition packageDefinition = fetchEntityFromConfig(packageId);

String etag = etagFor(packageDefinition);
if (fresh(request, etag)) {
return notModified(response);
}
setEtagHeader(packageDefinition, response);

return writerForTopLevelObject(request, response, outputWriter -> PackageDefinitionRepresenter.toJSON(outputWriter, packageDefinition));
}

String create(Request request, Response response) {
PackageDefinition packageDefinition = buildEntityFromRequestBody(request);
packageDefinition.ensureIdExists();
HttpLocalizedOperationResult result = new HttpLocalizedOperationResult();
packageDefinitionService.createPackage(packageDefinition, packageDefinition.getRepository().getId(), currentUsername(), result);
return handleCreateOrUpdateResponse(request, response, packageDefinition, result);
}

String update(Request request, Response response) {
String oldPackageId = request.params("package_id");
PackageDefinition newPackageDefinition = buildEntityFromRequestBody(request);
PackageDefinition oldPackageDefinition = fetchEntityFromConfig(oldPackageId);
String md5 = entityHashingService.md5ForEntity(oldPackageDefinition);
HttpLocalizedOperationResult result = new HttpLocalizedOperationResult();

if (isPutRequestStale(request, oldPackageDefinition)) {
throw haltBecauseEtagDoesNotMatch("packageDefinition", oldPackageId);
}

packageDefinitionService.updatePackage(oldPackageId, newPackageDefinition, md5, currentUsername(), result);

setEtagHeader(newPackageDefinition, response);
return handleCreateOrUpdateResponse(request, response, newPackageDefinition, result);
}

String remove(Request request, Response response) {
String packageId = request.params("package_id");
HttpLocalizedOperationResult result = new HttpLocalizedOperationResult();
PackageDefinition packageDefinition = fetchEntityFromConfig(packageId);

packageDefinitionService.deletePackage(packageDefinition, currentUsername(), result);

return handleSimpleMessageResponse(response, result);
}

@Override
public String etagFor(PackageDefinition entityFromServer) {
return entityHashingService.md5ForEntity(entityFromServer);
}

@Override
public EntityType getEntityType() {
return EntityType.PackageDefinition;
}

@Override
public PackageDefinition doFetchEntityFromConfig(String packageId) {
return packageDefinitionService.find(packageId);
}

@Override
public PackageDefinition buildEntityFromRequestBody(Request req) {
JsonReader jsonReader = GsonTransformer.getInstance().jsonReaderFrom(req.body());
return PackageDefinitionRepresenter.fromJSON(jsonReader);
}

@Override
public Consumer<OutputWriter> jsonWriter(PackageDefinition packages) {
return outputWriter -> PackageDefinitionRepresenter.toJSON(outputWriter, packages);
}
}
@@ -0,0 +1,64 @@
/*
* 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.packages.representers;

import com.thoughtworks.go.api.base.OutputWriter;
import com.thoughtworks.go.api.representers.ConfigurationPropertyRepresenter;
import com.thoughtworks.go.api.representers.ErrorGetter;
import com.thoughtworks.go.api.representers.JsonReader;
import com.thoughtworks.go.domain.config.ConfigurationProperty;
import com.thoughtworks.go.domain.packagerepository.PackageDefinition;
import com.thoughtworks.go.domain.packagerepository.PackageRepository;
import com.thoughtworks.go.spark.Routes;

import java.util.HashMap;
import java.util.List;

public class PackageDefinitionRepresenter {
public static void toJSON(OutputWriter outputWriter, PackageDefinition packageDefinition) {

outputWriter.addLinks(linksWriter -> {
linksWriter.addLink("self", Routes.Packages.self(packageDefinition.getId()));
linksWriter.addAbsoluteLink("doc", Routes.Packages.DOC);
linksWriter.addLink("find", Routes.Packages.FIND);
});
outputWriter.add("name", packageDefinition.getName());
outputWriter.add("id", packageDefinition.getId());
outputWriter.add("auto_update", packageDefinition.isAutoUpdate());
outputWriter.addChild("package_repo", childWriter -> PackageRepositoryRepresenter.toJSON(childWriter, packageDefinition.getRepository()));
outputWriter.addChildList("configuration", configWriter ->
ConfigurationPropertyRepresenter.toJSON(configWriter, packageDefinition.getConfiguration()));
if (!packageDefinition.errors().isEmpty()) {
outputWriter.addChild("errors", errorWriter -> {
HashMap<String, String> errorMapping = new HashMap<>();
new ErrorGetter(errorMapping).toJSON(errorWriter, packageDefinition);
});
}
}

public static PackageDefinition fromJSON(JsonReader jsonReader) {
PackageDefinition packageDefinition = new PackageDefinition();
jsonReader.readStringIfPresent("id", packageDefinition::setId);
jsonReader.readStringIfPresent("name", packageDefinition::setName);
List<ConfigurationProperty> configuration = ConfigurationPropertyRepresenter.fromJSONArray(jsonReader, "configuration");
packageDefinition.addConfigurations(configuration);
packageDefinition.setAutoUpdate(jsonReader.getBoolean("auto_update"));
PackageRepository packageRepo = PackageRepositoryRepresenter.fromJSON(jsonReader.readJsonObject("package_repo"));
packageDefinition.setRepository(packageRepo);
return packageDefinition;
}
}
@@ -0,0 +1,39 @@
/*
* 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.packages.representers;

import com.thoughtworks.go.api.base.OutputWriter;
import com.thoughtworks.go.domain.packagerepository.PackageDefinition;
import com.thoughtworks.go.spark.Routes;

import java.util.List;

import static com.thoughtworks.go.CurrentGoCDVersion.apiDocsUrl;

public class PackageDefinitionsRepresenter {
public static void toJSON(OutputWriter outputWriter, List<PackageDefinition> packages) {
outputWriter.addLinks(outputLinkWriter -> {
outputLinkWriter.addLink("self", Routes.Packages.BASE);
outputLinkWriter.addAbsoluteLink("doc", apiDocsUrl("#packages"));
});
outputWriter.addEmbedded(embeddedWriter -> {
embeddedWriter.addChildList("packages", listWriter -> {
packages.forEach(packageDefinition -> listWriter.addChild(childWriter -> PackageDefinitionRepresenter.toJSON(childWriter, packageDefinition)));
});
});
}
}
@@ -0,0 +1,43 @@
/*
* 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.packages.representers;

import com.thoughtworks.go.api.base.OutputWriter;
import com.thoughtworks.go.api.representers.JsonReader;
import com.thoughtworks.go.domain.packagerepository.PackageRepository;
import com.thoughtworks.go.spark.Routes;

import java.util.function.Consumer;

public class PackageRepositoryRepresenter {
public static void toJSON(OutputWriter outputWriter, PackageRepository packageRepository) {
outputWriter.addLinks(linkWriter -> {
linkWriter.addLink("self", Routes.PackageRepo.self(packageRepository.getId()));
linkWriter.addAbsoluteLink("doc", Routes.PackageRepo.DOC);
linkWriter.addLink("find", Routes.PackageRepo.FIND);
});
outputWriter.add("id", packageRepository.getId());
outputWriter.add("name", packageRepository.getName());
}

public static PackageRepository fromJSON(JsonReader jsonReader) {
PackageRepository packageRepository = new PackageRepository();
jsonReader.readStringIfPresent("id", packageRepository::setId);
jsonReader.readStringIfPresent("name", packageRepository::setName);
return packageRepository;
}
}

0 comments on commit fb04833

Please sign in to comment.