Skip to content

Commit

Permalink
chore: fcli fod release create enhancements
Browse files Browse the repository at this point in the history
feat: `fcli fod release create`: Add support for creating parent application & microservice if not existing

feat: `fcli fod release create`: Throw user-friendly error when trying to copy release from different application

feat: `fcli fod release create`: Ignore `--copy-from` if equal to release being created

feat: `fcli fod release create`: Ignore `--copy-from` if first release on new application
  • Loading branch information
rsenden committed Oct 29, 2024
1 parent fecf423 commit 576b620
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
import static com.fortify.cli.common.util.DisableTest.TestType.MULTI_OPT_PLURAL_NAME;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.fasterxml.jackson.databind.JsonNode;
import com.fortify.cli.common.cli.util.EnvSuffix;
Expand All @@ -27,11 +24,7 @@
import com.fortify.cli.common.util.DisableTest;
import com.fortify.cli.common.util.StringUtils;
import com.fortify.cli.fod._common.output.cli.cmd.AbstractFoDJsonNodeOutputCommand;
import com.fortify.cli.fod._common.util.FoDEnums;
import com.fortify.cli.fod.access_control.helper.FoDUserGroupHelper;
import com.fortify.cli.fod.access_control.helper.FoDUserHelper;
import com.fortify.cli.fod.app.attr.cli.mixin.FoDAttributeUpdateOptions;
import com.fortify.cli.fod.app.attr.helper.FoDAttributeHelper;
import com.fortify.cli.fod.app.cli.mixin.FoDAppTypeOptions;
import com.fortify.cli.fod.app.cli.mixin.FoDCriticalityTypeOptions;
import com.fortify.cli.fod.app.cli.mixin.FoDMicroserviceAndReleaseNameResolverMixin;
Expand Down Expand Up @@ -85,26 +78,19 @@ public JsonNode getJsonNode(UnirestInstance unirest) {
var releaseNameDescriptor = releaseNameResolverMixin.getMicroserviceAndReleaseNameDescriptor();
var microserviceName = releaseNameDescriptor.getMicroserviceName();
validateMicroserviceName(microserviceName);

var ownerId = FoDUserHelper.getUserDescriptor(unirest, owner, true).getUserId();
List<String> microservices = StringUtils.isBlank(microserviceName)
? Collections.emptyList() : new ArrayList<>(Arrays.asList(microserviceName));
FoDAppCreateRequest appCreateRequest = FoDAppCreateRequest.builder()
.applicationName(applicationName)
.applicationDescription(description)
.businessCriticalityType(criticalityType.getCriticalityType().name())
.emailList(FoDAppHelper.getEmailList(notifications))
.releaseName(releaseNameDescriptor.getReleaseName())
.businessCriticality(criticalityType.getCriticalityType())
.notify(notifications)
.microserviceAndReleaseNameDescriptor(releaseNameDescriptor)
.releaseDescription(releaseDescription)
.sdlcStatusType(String.valueOf(sdlcStatus.getSdlcStatusType()))
.ownerId(ownerId)
.applicationType(appType.getAppType().getFoDValue())
.hasMicroservices(appType.getAppType().isMicroservice())
.microservices(FoDAppHelper.getMicroservicesNode(microservices))
.attributes(FoDAttributeHelper.getAttributesNode(unirest, FoDEnums.AttributeTypes.All,
appAttrs.getAttributes(), autoRequiredAttrs))
.userGroupIds(FoDUserGroupHelper.getUserGroupsNode(unirest, userGroups)).build();

.sdlcStatus(sdlcStatus.getSdlcStatusType())
.owner(unirest, owner)
.appType(appType.getAppType())
.autoAttributes(unirest, appAttrs.getAttributes(), autoRequiredAttrs)
.userGroups(unirest, userGroups)
.build().validate();
return FoDAppHelper.createApp(unirest, appCreateRequest).asJsonNode();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,29 @@
*******************************************************************************/
package com.fortify.cli.fod.app.helper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.formkiq.graalvm.annotations.Reflectable;
import com.fortify.cli.common.json.JsonHelper;
import com.fortify.cli.common.util.StringUtils;
import com.fortify.cli.fod._common.util.FoDEnums;
import com.fortify.cli.fod.access_control.helper.FoDUserGroupHelper;
import com.fortify.cli.fod.access_control.helper.FoDUserHelper;
import com.fortify.cli.fod.app.attr.helper.FoDAttributeHelper;
import com.fortify.cli.fod.app.cli.mixin.FoDAppTypeOptions.FoDAppType;
import com.fortify.cli.fod.app.cli.mixin.FoDCriticalityTypeOptions.FoDCriticalityType;
import com.fortify.cli.fod.app.cli.mixin.FoDSdlcStatusTypeOptions.FoDSdlcStatusType;
import com.fortify.cli.fod.release.helper.FoDQualifiedReleaseNameDescriptor;

import kong.unirest.UnirestInstance;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -35,10 +55,98 @@ public class FoDAppCreateRequest {
private String sdlcStatusType;
private Integer ownerId;
private String applicationType;
private Boolean hasMicroservices;
@Builder.Default private boolean hasMicroservices = false;
private JsonNode microservices;
private String releaseMicroserviceName;
private JsonNode attributes;
private JsonNode userGroupIds;
private Boolean autoRequiredAttrs;

@JsonIgnore
public final ObjectNode asObjectNode() {
ObjectNode body = JsonHelper.getObjectMapper().valueToTree(this);
// if microservice, remove applicationType field
if (isHasMicroservices()) {
body.remove("applicationType");
}
return body;
}

@JsonIgnore
public final FoDAppCreateRequest validate(Consumer<List<String>> validationMessageConsumer) {
var messages = new ArrayList<String>();
validateRequired(messages, applicationName, "Required application name not specified");
validateRequired(messages, businessCriticalityType, "Required application business criticality not specified");
validateRequired(messages, releaseName, "Required release name not specified");
validateRequired(messages, sdlcStatusType, "Required release SDLC status not specified");
validateRequired(messages, ownerId, "Required application owner not specified");
validateRequired(messages, applicationType, "Required application type not specified");
if ( hasMicroservices ) {
validateRequired(messages, releaseMicroserviceName, "Required release microservice name not specified");
}
if ( !messages.isEmpty() ) {
validationMessageConsumer.accept(messages);
}
return this;
}

@JsonIgnore
public final FoDAppCreateRequest validate() {
return validate(messages->{throw new IllegalArgumentException("Unable to create application:\n\t"+String.join("\n\t", messages)); });
}

@JsonIgnore
private final void validateRequired(List<String> messages, Object obj, String message) {
if ( obj==null || (obj instanceof String && StringUtils.isBlank((String)obj)) ) {
messages.add(message);
}
}

public static class FoDAppCreateRequestBuilder {
public FoDAppCreateRequestBuilder appType(FoDAppType appType) {
if ( appType==null ) { return hasMicroservices(false).applicationType(null); }
else { return hasMicroservices(appType.isMicroservice()).applicationType(appType.getFoDValue()); }
}

public FoDAppCreateRequestBuilder autoAttributes(UnirestInstance unirest, Map<String, String> attributes, boolean autoRequiredAttrs) {
return attributes(FoDAttributeHelper.getAttributesNode(unirest, FoDEnums.AttributeTypes.All, attributes, autoRequiredAttrs));
}

public FoDAppCreateRequestBuilder businessCriticality(FoDCriticalityType businessCriticalityType) {
return businessCriticalityType(businessCriticalityType==null ? null : businessCriticalityType.name());
}

public FoDAppCreateRequestBuilder notify(ArrayList<String> notifications) {
return emailList(FoDAppHelper.getEmailList(notifications));
}

public FoDAppCreateRequestBuilder microserviceName(String microserviceName) {
List<String> microservices = StringUtils.isBlank(microserviceName)
? Collections.emptyList() : new ArrayList<>(Arrays.asList(microserviceName));
microservices(FoDAppHelper.getMicroservicesNode(microservices));
return releaseMicroserviceName(microserviceName);
}

public FoDAppCreateRequestBuilder microserviceAndReleaseNameDescriptor(FoDMicroserviceAndReleaseNameDescriptor microserviceAndReleaseNameDescriptor) {
microserviceName(microserviceAndReleaseNameDescriptor==null ? null : microserviceAndReleaseNameDescriptor.getMicroserviceName());
return releaseName(microserviceAndReleaseNameDescriptor==null ? null : microserviceAndReleaseNameDescriptor.getReleaseName());
}

public FoDAppCreateRequestBuilder releaseNameDescriptor(FoDQualifiedReleaseNameDescriptor releaseNameDescriptor) {
applicationName(releaseNameDescriptor==null ? null : releaseNameDescriptor.getAppName());
microserviceName(releaseNameDescriptor==null ? null : releaseNameDescriptor.getMicroserviceName());
return releaseName(releaseNameDescriptor==null ? null : releaseNameDescriptor.getReleaseName());
}

public FoDAppCreateRequestBuilder owner(UnirestInstance unirest, String owner) {
return ownerId(owner==null ? null : FoDUserHelper.getUserDescriptor(unirest, owner, true).getUserId());
}

public FoDAppCreateRequestBuilder sdlcStatus(FoDSdlcStatusType sdlcStatusType) {
return sdlcStatusType(sdlcStatusType==null ? null : sdlcStatusType.name());
}

public FoDAppCreateRequestBuilder userGroups(UnirestInstance unirest, ArrayList<String> userGroups) {
return userGroupIds(FoDUserGroupHelper.getUserGroupsNode(unirest, userGroups));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fortify.cli.common.json.JsonHelper;
import com.fortify.cli.common.util.StringUtils;
import com.fortify.cli.fod._common.rest.FoDUrls;
import com.fortify.cli.fod._common.rest.helper.FoDDataHelper;
import com.fortify.cli.fod.app.cli.mixin.FoDAppTypeOptions.FoDAppType;
Expand Down Expand Up @@ -62,16 +61,8 @@ public static final FoDAppDescriptor getAppDescriptor(UnirestInstance unirest, S
}

public static final FoDAppDescriptor createApp(UnirestInstance unirest, FoDAppCreateRequest appCreateRequest) {
ObjectNode body = objectMapper.valueToTree(appCreateRequest);
// if microservice, remove applicationType field and set releaseMicroserviceName if not already set
if (appCreateRequest.getHasMicroservices()) {
body.remove("applicationType");
if (StringUtils.isBlank(appCreateRequest.getReleaseMicroserviceName())) {
body.replace("releaseMicroserviceName", appCreateRequest.getMicroservices().get(0));
}
}
var appId = unirest.post(FoDUrls.APPLICATIONS)
.body(body).asObject(JsonNode.class).getBody().get("applicationId").asText();
.body(appCreateRequest.asObjectNode()).asObject(JsonNode.class).getBody().get("applicationId").asText();
return getAppDescriptor(unirest, appId, true);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ public static final FoDMicroserviceDescriptor createMicroservice(UnirestInstance
.body(body).asObject(JsonNode.class).getBody();
return getDescriptor(appDescriptor, response, msRequest.getMicroserviceName());
}

public static final FoDMicroserviceDescriptor createMicroservice(UnirestInstance unirest, FoDAppDescriptor appDescriptor, String microserviceName) {
var request = FoDMicroserviceUpdateRequest.builder().microserviceName(microserviceName).build();
return createMicroservice(unirest, appDescriptor, request);
}

public static final FoDMicroserviceDescriptor updateMicroservice(UnirestInstance unirest, FoDMicroserviceDescriptor currentMs, FoDMicroserviceUpdateRequest msRequest) {
FoDAppDescriptor appDescriptor = FoDAppHelper.getAppDescriptor(unirest, currentMs.getApplicationId(), true);
Expand Down
Loading

0 comments on commit 576b620

Please sign in to comment.