Skip to content

Commit

Permalink
feat: Add fcli fod release wait-for command to wait for release(s) …
Browse files Browse the repository at this point in the history
…to leave suspended state (resolves #624)
  • Loading branch information
rsenden committed Oct 25, 2024
1 parent 7920a40 commit 0cdde30
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
FoDReleaseUpdateCommand.class,
FoDReleaseDeleteCommand.class,
FoDReleaseAssessmentTypeListCommand.class,
FoDReleaseScanListCommand.class
FoDReleaseScanListCommand.class,
FoDReleaseWaitForCommand.class
}
)
@DefaultVariablePropertyName("releaseId")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright 2021, 2023 Open Text.
*
* The only warranties for products and services of Open Text
* and its affiliates and licensors ("Open Text") are as may
* be set forth in the express warranty statements accompanying
* such products and services. Nothing herein should be construed
* as constituting an additional warranty. Open Text shall not be
* liable for technical or editorial errors or omissions contained
* herein. The information contained herein is subject to change
* without notice.
*******************************************************************************/

package com.fortify.cli.fod.release.cli.cmd;

import java.util.Set;

import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins;
import com.fortify.cli.common.rest.cli.cmd.AbstractWaitForCommand;
import com.fortify.cli.common.rest.wait.WaitHelper.WaitHelperBuilder;
import com.fortify.cli.fod._common.cli.mixin.FoDDelimiterMixin;
import com.fortify.cli.fod._common.session.cli.mixin.FoDUnirestInstanceSupplierMixin;
import com.fortify.cli.fod.release.cli.mixin.FoDReleaseByQualifiedNameOrIdResolverMixin;

import kong.unirest.UnirestInstance;
import lombok.Getter;
import picocli.CommandLine.Command;
import picocli.CommandLine.Mixin;
import picocli.CommandLine.Option;

@Command(name = OutputHelperMixins.WaitFor.CMD_NAME)
public final class FoDReleaseWaitForCommand extends AbstractWaitForCommand {
@Getter @Mixin private FoDUnirestInstanceSupplierMixin unirestInstanceSupplier;
@Mixin private FoDDelimiterMixin delimiterMixin; // Is automatically injected in resolver mixins
@Mixin private FoDReleaseByQualifiedNameOrIdResolverMixin.PositionalParameterMulti releaseResolver;
@Option(names={"-s", "--suspended"}, paramLabel="true|false", required=true, defaultValue="false", arity="1")
private boolean suspended;

@Override
protected final WaitHelperBuilder configure(UnirestInstance unirest, WaitHelperBuilder builder) {
return builder
.recordsSupplier(releaseResolver::getReleaseDescriptorJsonNodes)
.currentStateProperty("suspended")
.knownStates("true", "false")
.failureStates()
.matchStates(Set.of(String.valueOf(suspended)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@

package com.fortify.cli.fod.release.cli.mixin;

import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.databind.JsonNode;
import com.fortify.cli.common.cli.util.EnvSuffix;
import com.fortify.cli.common.util.StringUtils;
import com.fortify.cli.fod._common.cli.mixin.FoDDelimiterMixin;
Expand Down Expand Up @@ -43,6 +48,23 @@ public String getReleaseId(UnirestInstance unirest) {
return descriptor==null ? null : descriptor.getReleaseId();
}
}

public static abstract class AbstractFoDMultiQualifiedReleaseNameOrIdResolverMixin implements IFoDDelimiterMixinAware {
@Setter private FoDDelimiterMixin delimiterMixin;
public abstract String[] getQualifiedReleaseNamesOrIds();

public FoDReleaseDescriptor[] getReleaseDescriptors(UnirestInstance unirest, String... fields) {
return Stream.of(getQualifiedReleaseNamesOrIds()).map(nameOrId->FoDReleaseHelper.getReleaseDescriptor(unirest, nameOrId, delimiterMixin.getDelimiter(), true, fields)).toArray(FoDReleaseDescriptor[]::new);
}

public Collection<JsonNode> getReleaseDescriptorJsonNodes(UnirestInstance unirest, String... fields) {
return Stream.of(getReleaseDescriptors(unirest, fields)).map(FoDReleaseDescriptor::asJsonNode).collect(Collectors.toList());
}

public Integer[] getReleaseIds(UnirestInstance unirest) {
return Stream.of(getReleaseDescriptors(unirest, "releaseId")).map(FoDReleaseDescriptor::getReleaseId).toArray(Integer[]::new);
}
}

public static class RequiredOption extends AbstractFoDQualifiedReleaseNameOrIdResolverMixin {
@Option(names = {"--release", "--rel"}, required = true, paramLabel = "id|app[:ms]:rel", descriptionKey = "fcli.fod.release.resolver.name-or-id")
Expand All @@ -63,4 +85,9 @@ public static class OptionalCopyFromOption extends AbstractFoDQualifiedReleaseNa
@Option(names = {"--copy-from"}, required = false, paramLabel = "id|app[:ms]:rel", descriptionKey = "fcli.fod.release.resolver.copy-from.nameOrId")
@Getter private String qualifiedReleaseNameOrId;
}

public static class PositionalParameterMulti extends AbstractFoDMultiQualifiedReleaseNameOrIdResolverMixin {
@Parameters(index = "0", arity = "1..", paramLabel="id|app[:ms]:rel", descriptionKey = "fcli.fod.release.resolver.multi-name-or-id")
@Getter private String[] qualifiedReleaseNamesOrIds;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ fcli.fod.scan.in-progress-action = The action to use if a scan is already in pro
fcli.fod.scan.remediation-preference = The remediation preference to use. Valid values: ${COMPLETION-CANDIDATES}.
fcli.fod.microservice.resolver.name = Microservice name in the format <application>:<microservice>.
fcli.fod.release.resolver.name-or-id = Release id or <application>[:<microservice>]:<release> name.
fcli.fod.release.resolver.multi-name-or-id = One or more release id's or <application>[:<microservice>]:<release> names.
fcli.fod.release.resolver.name = Release name in the format <application>[:<microservice>]:<release>.
fcli.fod.import.sbom-format = The SBOM format to import. If empty Cyclone DX format is assumed.
fcli.fod.user.user-name-or-id = User id or username. Note that numeric values are always interpreted \
Expand Down Expand Up @@ -363,7 +364,11 @@ fcli.fod.release.create.usage.header = Create a new application release. \
fcli.fod.release.create.application-name = The id or name of the application to create the release on.
fcli.fod.release.create.release-name = The name of the release to create for the application.
fcli.fod.release.create.description = Description of the release.
fcli.fod.release.create.copy-from = The id or name of a release to copy existing state from.
fcli.fod.release.create.copy-from = The id or name of a release to copy existing state from. Note that \
FoD will put the release in 'suspended' state until copying is complete, during which time scan \
requests and other operations may be rejected. If you want to run any other operations on the release, \
it is recommended to first invoke the `fcli fod release wait-for` command to wait until the release \
leaves suspended state.
fcli.fod.release.create.microservice = The id or name of the microservice to create the release on.
fcli.fod.release.create.status = SDLC lifecycle status of the release. Valid values: ${COMPLETION-CANDIDATES}.
fcli.fod.release.create.attr = Attribute id or name and its value to set on the release. \
Expand All @@ -387,6 +392,19 @@ fcli.fod.release.update.attr = Attribute id or name and its value to set on the
fcli.fod.release.list-assessment-types.usage.header = List assessment types for a given release.
fcli.fod.release.list-assessment-types.scan-types = Comma-separated list of scan types for which to list assessment types. Default value: ${DEFAULT-VALUE}. Valid values: ${COMPLETION-CANDIDATES}.
fcli.fod.release.list-scans.usage.header = List scans for a given release.
fcli.fod.release.wait-for.usage.header = Wait for one or more scans to reach or exit suspended state.
fcli.fod.release.wait-for.usage.description.0 = Although this command offers a lot of options to \
cover many different use cases, you can simply pass one or more release names or id's to wait until \
those releases leave 'suspended' state. \
%n%nMost common use case is to invoke this wait-for command after creating a new release through the \
`fcli fod release create` command with the `--copy-from` option; FoD will put the newly created \
release in 'suspended' state until copying is completed, during which time scan requests and other \
operations may be rejected. \
%n%nNote that contrary to other fcli wait-for commands, any options related to unknown or failure state \
handling are not applicable to this wait-for command and will be ignored.
fcli.fod.release.wait-for.until = Wait until either any or all releases match. If neither --until or --while are specified, default is to wait until all releases match.
fcli.fod.release.wait-for.while = Wait while either any or all releases match.
fcli.fod.release.wait-for.suspended = Suspended state against which to match the given releases; may be `false` (default) or `true`.

# fcli fod assessment-type
fcli.fod.assessment-type.usage.header = Manage FoD assessment types.
Expand Down Expand Up @@ -884,6 +902,7 @@ fcli.fod.app.output.table.options = applicationId,applicationName,fcliApplicatio
fcli.fod.app.scan.output.table.options = scanId,scanType,analysisStatusType,applicationName,microserviceName,releaseName,startedDateTime,completedDateTime,scanMethodTypeName
fcli.fod.microservice.output.table.options = microserviceId,microserviceName,applicationName
fcli.fod.release.output.table.options = releaseId,releaseName,microserviceName,applicationName,sdlcStatusType
fcli.fod.release.wait-for.output.table.options = releaseId,releaseName,microserviceName,applicationName,suspended
fcli.fod.release.scan.output.table.options = scanId,scanType,analysisStatusType,applicationName,microserviceName,releaseName,startedDateTime,completedDateTime,scanMethodTypeName
fcli.fod.release.assessment-type.output.table.options = assessmentTypeId,name,scanType,frequencyType,unitInfo,entitlementId,entitlementDescription
fcli.fod.entitlement.output.table.options = entitlementId,entitlementDescription,startDate,endDate,unitInfo
Expand Down

0 comments on commit 0cdde30

Please sign in to comment.