Skip to content

Commit

Permalink
[#600] Add config-stability-level and package-stability-level attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
spyrkob committed Mar 25, 2024
1 parent e24dc45 commit b3eeb4e
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 29 deletions.
17 changes: 16 additions & 1 deletion dist/docs/guide/usage/install.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,19 @@ $ ./prospero.sh install \ #<2>
<1> Generates a repository at `/path/to/local_repo`
<2> Installs the server using content of `/path/to/local_repo` instead of default repositories
NOTE: When using a <groupId>:<artifactId> to resolve manifest from a repository, the manifest artifact has to have accompanying Maven metadata (maven-metadata.xml).
NOTE: When using a <groupId>:<artifactId> to resolve manifest from a repository, the manifest artifact has to have accompanying Maven metadata (maven-metadata.xml).
#### Selecting stability level of provisioned server
Some feature packs may contain experimental or preview features not intended to be made available by default. To separate those features from stable ones, feature packs may segregate the features into `stability-levels`. At the provisioning time, the user is able to change the default stability level of the feature pack by using the `--stability` flag.
[source, bash]
----
$ ./prospero.sh install \ #<1>
--dir wfly-31 \
--profile wildfly \
--manifest /path/to/wildfly-manifest.yaml \
--stability preview
----
For more fine-grained control, the level of installed packages and configuration can be set separately using `--config-stability` and `--package-stability` flags.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ private Commands() {
public static final String CHANNELS = "--channels";
public static final String REPOSITORIES = "--repositories";
public static final String SHADE_REPOSITORIES = "--shade-repositories";
public static final String STABILITY_LEVEL = "--stability-level";
public static final String STABILITY_LEVEL = "--stability";
public static final String CONFIG_STABILITY_LEVEL = "--config-stability";
public static final String PACKAGE_STABILITY_LEVEL = "--package-stability";
public static final String DEFINITION = "--definition";
public static final String DIR = "--dir";
public static final String FPL = "--fpl";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Locale;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.jboss.galleon.Constants;
import org.jboss.galleon.api.config.GalleonProvisioningConfig;

Expand Down Expand Up @@ -79,23 +80,17 @@ public class InstallCommand extends AbstractInstallCommand {
)
List<String> shadowRepositories = new ArrayList<>();

private static final List<String> STABILITY_LEVELS = List.of(Constants.STABILITY_EXPERIMENTAL,
protected static final List<String> STABILITY_LEVELS = List.of(Constants.STABILITY_EXPERIMENTAL,
Constants.STABILITY_PREVIEW,
Constants.STABILITY_DEFAULT,
Constants.STABILITY_COMMUNITY);

private static class StabilityCandidates implements Iterable<String> {
@Override
public Iterator<String> iterator() {
return STABILITY_LEVELS.stream().map(String::toLowerCase).iterator();
}
}
@CommandLine.Option(
names = CliConstants.STABILITY_LEVEL,
completionCandidates = StabilityCandidates.class
@CommandLine.ArgGroup(
headingKey = "stability_level_header",
exclusive = false,
order = 9
)
String stabilityLevel;

StabilityLevels stabilityLevels = new StabilityLevels();

static class FeaturePackOrDefinition {
@CommandLine.Option(
Expand Down Expand Up @@ -159,9 +154,7 @@ public Integer call() throws Exception {
}
}

if (stabilityLevel != null && !STABILITY_LEVELS.contains(stabilityLevel.toLowerCase(Locale.ROOT))) {
throw CliMessages.MESSAGES.unknownStabilityLevel(stabilityLevel, STABILITY_LEVELS);
}
stabilityLevels.verify();

if (featurePackOrDefinition.definition.isPresent()) {
final Path definition = featurePackOrDefinition.definition.get().toAbsolutePath();
Expand All @@ -171,7 +164,9 @@ public Integer call() throws Exception {
verifyTargetDirectoryIsEmpty(directory);

final ProvisioningDefinition provisioningDefinition = buildDefinition()
.setStabilityLevel(stabilityLevel==null?null:stabilityLevel.toLowerCase(Locale.ROOT))
.setStabilityLevel(stabilityLevels.stabilityLevel==null?null:stabilityLevels.stabilityLevel.toLowerCase(Locale.ROOT))
.setPackageStabilityLevel(stabilityLevels.packageStabilityLevel==null?null:stabilityLevels.packageStabilityLevel.toLowerCase(Locale.ROOT))
.setConfigStabilityLevel(stabilityLevels.configStabilityLevel==null?null:stabilityLevels.configStabilityLevel.toLowerCase(Locale.ROOT))
.build();
final MavenOptions mavenOptions = getMavenOptions();
final GalleonProvisioningConfig provisioningConfig = provisioningDefinition.toProvisioningConfig();
Expand Down Expand Up @@ -243,4 +238,51 @@ private boolean isStandardFpl(String fpl) {
return KnownFeaturePacks.isWellKnownName(fpl);
}

private static class StabilityCandidates implements Iterable<String> {
@Override
public Iterator<String> iterator() {
return STABILITY_LEVELS.stream().map(String::toLowerCase).iterator();
}
}

static class StabilityLevels {
@CommandLine.Option(
names = CliConstants.STABILITY_LEVEL,
completionCandidates = StabilityCandidates.class,
paramLabel = "stability-level"
)
String stabilityLevel;

@CommandLine.Option(
names = CliConstants.CONFIG_STABILITY_LEVEL,
completionCandidates = StabilityCandidates.class,
paramLabel = "stability-level"
)
String configStabilityLevel;

@CommandLine.Option(
names = CliConstants.PACKAGE_STABILITY_LEVEL,
completionCandidates = StabilityCandidates.class,
paramLabel = "stability-level"
)
String packageStabilityLevel;

public void verify() {
if (StringUtils.isNotEmpty(stabilityLevel) && StringUtils.isNotEmpty(configStabilityLevel)) {
throw CliMessages.MESSAGES.exclusiveOptions(CliConstants.STABILITY_LEVEL, CliConstants.CONFIG_STABILITY_LEVEL);
}
if (StringUtils.isNotEmpty(stabilityLevel) && StringUtils.isNotEmpty(packageStabilityLevel)) {
throw CliMessages.MESSAGES.exclusiveOptions(CliConstants.STABILITY_LEVEL, CliConstants.PACKAGE_STABILITY_LEVEL);
}
if (stabilityLevel != null && !STABILITY_LEVELS.contains(stabilityLevel.toLowerCase(Locale.ROOT))) {
throw CliMessages.MESSAGES.unknownStabilityLevel(stabilityLevel, STABILITY_LEVELS);
}
if (configStabilityLevel != null && !STABILITY_LEVELS.contains(configStabilityLevel.toLowerCase(Locale.ROOT))) {
throw CliMessages.MESSAGES.unknownStabilityLevel(configStabilityLevel, STABILITY_LEVELS);
}
if (packageStabilityLevel != null && !STABILITY_LEVELS.contains(packageStabilityLevel.toLowerCase(Locale.ROOT))) {
throw CliMessages.MESSAGES.unknownStabilityLevel(packageStabilityLevel, STABILITY_LEVELS);
}
}
}
}
9 changes: 8 additions & 1 deletion prospero-cli/src/main/resources/UsageMessages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,14 @@ yes = Performs the operation without asking for a confirmation.
path = Path of the file to export to or import from.
candidate-dir = Path of the server candidate created using the @|bold --update prepare|@ command.
rm = Remove the candidate server after applying it.
stability-level = The minimal stability level of provisioned server. Valid options are ${COMPLETION-CANDIDATES}.
stability_level_header=%nProvisioning stability levels:%n
stability.0 = Select the minimal stability of features included in the provisioned server. Setting this property equates to setting both\
\ @|bold --config-stability|@ and @|bold --package-stability|@ to the same value.
stability.1 = Valid options are ${COMPLETION-CANDIDATES}.
config-stability.0 = Select the minimal stability of configurations provisioned in the server. Cannot be used together with @|bold --stability|@.
config-stability.1 = Valid options are ${COMPLETION-CANDIDATES}.
package-stability.0 = Select the minimal stability of provisioned packages (e.g. JBoss Modules modules) in the server. Cannot be used together with @|bold --stability|@.
package-stability.1 = Valid options are ${COMPLETION-CANDIDATES}.

${prospero.dist.name}.update.prepare.candidate-dir = Target directory where the candidate server will be provisioned. The existing server is not updated.
${prospero.dist.name}.update.subscribe.product = Specify the product name. This must be a known feature pack supported by ${prospero.dist.name}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,90 @@ public void stabilityLevelIsPassedOn() throws Exception {
.contains(entry(Constants.STABILITY_LEVEL, "default"));
}

@Test
public void configStabilityLevelCantBeUsedWithStabilityLevel() throws Exception {
final File channelsFile = temporaryFolder.newFile();
Channel channel = createChannel("test", "test", "http://test.org", "org.test");
MetadataTestUtils.writeChannels(channelsFile.toPath(), List.of(channel));

int exitCode = commandLine.execute(CliConstants.Commands.INSTALL, CliConstants.DIR, "test",
CliConstants.FPL, "org.wildfly:wildfly-ee-galleon-pack",
CliConstants.CHANNELS, channelsFile.getAbsolutePath(),
CliConstants.STABILITY_LEVEL, "default",
CliConstants.CONFIG_STABILITY_LEVEL, "default");
assertEquals(ReturnCodes.INVALID_ARGUMENTS, exitCode);
assertThat(getErrorOutput()).contains(CliMessages.MESSAGES.exclusiveOptions(CliConstants.STABILITY_LEVEL, CliConstants.CONFIG_STABILITY_LEVEL).getMessage());
}

@Test
public void packageStabilityLevelCantBeUsedWithStabilityLevel() throws Exception {
final File channelsFile = temporaryFolder.newFile();
Channel channel = createChannel("test", "test", "http://test.org", "org.test");
MetadataTestUtils.writeChannels(channelsFile.toPath(), List.of(channel));

int exitCode = commandLine.execute(CliConstants.Commands.INSTALL, CliConstants.DIR, "test",
CliConstants.FPL, "org.wildfly:wildfly-ee-galleon-pack",
CliConstants.CHANNELS, channelsFile.getAbsolutePath(),
CliConstants.STABILITY_LEVEL, "default",
CliConstants.PACKAGE_STABILITY_LEVEL, "default");
assertEquals(ReturnCodes.INVALID_ARGUMENTS, exitCode);
assertThat(getErrorOutput())
.contains(CliMessages.MESSAGES.exclusiveOptions(CliConstants.STABILITY_LEVEL, CliConstants.PACKAGE_STABILITY_LEVEL).getMessage());
}

@Test
public void packageStabilityLevelCanBeUsedTogetherWithConfigStabilityLevel() throws Exception {
final File channelsFile = temporaryFolder.newFile();
Channel channel = createChannel("test", "test", "http://test.org", "org.test");
MetadataTestUtils.writeChannels(channelsFile.toPath(), List.of(channel));

int exitCode = commandLine.execute(CliConstants.Commands.INSTALL, CliConstants.DIR, "test",
CliConstants.FPL, "org.wildfly:wildfly-ee-galleon-pack",
CliConstants.CHANNELS, channelsFile.getAbsolutePath(),
CliConstants.CONFIG_STABILITY_LEVEL, "community",
CliConstants.PACKAGE_STABILITY_LEVEL, "experimental");
assertEquals(ReturnCodes.SUCCESS, exitCode);
Mockito.verify(provisionAction).provision(configCaptor.capture(), any(), any());
assertThat(configCaptor.getValue().getOptions())
.contains(entry(Constants.PACKAGE_STABILITY_LEVEL, "experimental"),
entry(Constants.CONFIG_STABILITY_LEVEL, "community"));
}

@Test
public void invalidStabilityLevelCausesAnError() throws Exception {
final File channelsFile = temporaryFolder.newFile();
Channel channel = createChannel("test", "test", "http://test.org", "org.test");
MetadataTestUtils.writeChannels(channelsFile.toPath(), List.of(channel));

int exitCode = commandLine.execute(CliConstants.Commands.INSTALL, CliConstants.DIR, "test",
CliConstants.FPL, "org.wildfly:wildfly-ee-galleon-pack",
CliConstants.CHANNELS, channelsFile.getAbsolutePath(),
CliConstants.STABILITY_LEVEL, "idontexist");
assertEquals(ReturnCodes.INVALID_ARGUMENTS, exitCode);
assertThat(getErrorOutput())
.contains(CliMessages.MESSAGES.unknownStabilityLevel("idontexist", InstallCommand.STABILITY_LEVELS).getMessage());

systemErrRule.clearLog();

exitCode = commandLine.execute(CliConstants.Commands.INSTALL, CliConstants.DIR, "test",
CliConstants.FPL, "org.wildfly:wildfly-ee-galleon-pack",
CliConstants.CHANNELS, channelsFile.getAbsolutePath(),
CliConstants.CONFIG_STABILITY_LEVEL, "idontexist");
assertEquals(ReturnCodes.INVALID_ARGUMENTS, exitCode);
assertThat(getErrorOutput())
.contains(CliMessages.MESSAGES.unknownStabilityLevel("idontexist", InstallCommand.STABILITY_LEVELS).getMessage());

systemErrRule.clearLog();

exitCode = commandLine.execute(CliConstants.Commands.INSTALL, CliConstants.DIR, "test",
CliConstants.FPL, "org.wildfly:wildfly-ee-galleon-pack",
CliConstants.CHANNELS, channelsFile.getAbsolutePath(),
CliConstants.PACKAGE_STABILITY_LEVEL, "idontexist");
assertEquals(ReturnCodes.INVALID_ARGUMENTS, exitCode);
assertThat(getErrorOutput())
.contains(CliMessages.MESSAGES.unknownStabilityLevel("idontexist", InstallCommand.STABILITY_LEVELS).getMessage());
}

@Override
protected MavenOptions getCapturedMavenOptions() throws Exception {
Mockito.verify(actionFactory).install(any(), mavenOptions.capture(), any());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import javax.xml.stream.XMLStreamException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.aether.repository.RemoteRepository;
import org.jboss.galleon.Constants;
import org.jboss.galleon.ProvisioningException;
Expand Down Expand Up @@ -89,12 +90,20 @@ public class ProvisioningDefinition {
private final URI definition;

private final String stabilityLevel;
private final String configStabilityLevel;
private final String packageStabilityLevel;

private ProvisioningDefinition(Builder builder) throws NoChannelException {
this.overrideRepositories.addAll(builder.overrideRepositories);
this.channelCoordinates.addAll(builder.channelCoordinates);

this.stabilityLevel = builder.stabilityLevel;
this.configStabilityLevel = builder.configStabilityLevel;
this.packageStabilityLevel = builder.packageStabilityLevel;
if (StringUtils.isNotEmpty(stabilityLevel) &&
(StringUtils.isNotEmpty(packageStabilityLevel) || StringUtils.isNotEmpty(configStabilityLevel))) {
throw new IllegalArgumentException("Provisioning option stabilityLevel cannot be used with packageStabilityLevel or configStabilityLevel");
}

if (builder.profile.isPresent()) {

Expand Down Expand Up @@ -156,18 +165,29 @@ public GalleonProvisioningConfig toProvisioningConfig() throws MetadataException
if (stabilityLevel != null) {
builder.addOption(Constants.STABILITY_LEVEL, stabilityLevel);
}
if (configStabilityLevel != null) {
builder.addOption(Constants.CONFIG_STABILITY_LEVEL, configStabilityLevel);
}
if (packageStabilityLevel != null) {
builder.addOption(Constants.PACKAGE_STABILITY_LEVEL, packageStabilityLevel);
}
return builder.build();

} else if (definition != null) {
try {
final GalleonProvisioningConfig config = GalleonUtils.loadProvisioningConfig(definition);
if (stabilityLevel == null) {
return config;
} else {
return GalleonProvisioningConfig.builder(config)
.addOption(Constants.STABILITY_LEVEL, stabilityLevel)
.build();
final GalleonProvisioningConfig.Builder builder = GalleonProvisioningConfig.builder(config);
if (StringUtils.isNotEmpty(stabilityLevel)) {
builder.addOption(Constants.STABILITY_LEVEL, stabilityLevel);
}
if (StringUtils.isNotEmpty(configStabilityLevel)) {
builder.addOption(Constants.CONFIG_STABILITY_LEVEL, configStabilityLevel);
}
if (StringUtils.isNotEmpty(packageStabilityLevel)) {
builder.addOption(Constants.PACKAGE_STABILITY_LEVEL, packageStabilityLevel);
}

return builder.build();
} catch (XMLStreamException e) {
throw ProsperoLogger.ROOT_LOGGER.unableToParseConfigurationUri(definition, e);
}
Expand Down Expand Up @@ -261,6 +281,8 @@ public static class Builder {
private List<ChannelCoordinate> channelCoordinates = Collections.emptyList();
private Optional<String> profile = Optional.empty();
private String stabilityLevel;
private String packageStabilityLevel;
private String configStabilityLevel;

public ProvisioningDefinition build() throws MetadataException, NoChannelException {
return new ProvisioningDefinition(this);
Expand Down Expand Up @@ -310,5 +332,15 @@ public Builder setStabilityLevel(String stabilityLevel) {
this.stabilityLevel = stabilityLevel;
return this;
}

public Builder setPackageStabilityLevel(String packageStabilityLevel) {
this.packageStabilityLevel = packageStabilityLevel;
return this;
}

public Builder setConfigStabilityLevel(String configStabilityLevel) {
this.configStabilityLevel = configStabilityLevel;
return this;
}
}
}
Loading

0 comments on commit b3eeb4e

Please sign in to comment.