Skip to content

Commit

Permalink
CLI add/remove registry commands
Browse files Browse the repository at this point in the history
  • Loading branch information
aloubyansky committed Aug 24, 2021
1 parent fb575c1 commit e85aab6
Show file tree
Hide file tree
Showing 15 changed files with 265 additions and 15 deletions.
4 changes: 3 additions & 1 deletion devtools/cli/src/main/java/io/quarkus/cli/Registry.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import picocli.CommandLine.Unmatched;

@CommandLine.Command(name = "registry", sortOptions = false, mixinStandardHelpOptions = false, header = "Manage extension registries.", subcommands = {
RegistryListCommand.class }, headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", optionListHeading = "%nOptions:%n")
RegistryAddCommand.class,
RegistryListCommand.class,
RegistryRemoveCommand.class }, headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", optionListHeading = "%nOptions:%n")
public class Registry extends BaseRegistryCommand {

@Unmatched // avoids throwing errors for unmatched arguments
Expand Down
74 changes: 74 additions & 0 deletions devtools/cli/src/main/java/io/quarkus/cli/RegistryAddCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.quarkus.cli;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import java.util.stream.Collectors;

import io.quarkus.cli.registry.BaseRegistryCommand;
import io.quarkus.cli.registry.RegistryClientMixin;
import io.quarkus.registry.config.RegistriesConfig;
import io.quarkus.registry.config.RegistriesConfigLocator;
import io.quarkus.registry.config.RegistryConfig;
import io.quarkus.registry.config.json.JsonRegistriesConfig;
import io.quarkus.registry.config.json.JsonRegistryConfig;
import io.quarkus.registry.config.json.RegistriesConfigMapperHelper;
import picocli.CommandLine;

@CommandLine.Command(name = "add", sortOptions = false, showDefaultValues = true, mixinStandardHelpOptions = false, header = "Add a Quarkus extension registry to the registry client configuration", description = "%n"
+ "This command will add a Quarkus extension registry to the registry client configuration unless it's already present", headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", parameterListHeading = "%n", optionListHeading = "Options:%n")
public class RegistryAddCommand extends BaseRegistryCommand {

@CommandLine.Mixin
protected RegistryClientMixin registryClient;

@CommandLine.Parameters(arity = "0..1", paramLabel = "REGISTRY-ID[,REGISTRY-ID]", description = "Registry ID to add to the registry client configuration%n"
+ " Example:%n"
+ " registry.quarkus.io%n"
+ " registry.quarkus.acme.com,registry.quarkus.io%n")
String registryIds;

@Override
public Integer call() throws Exception {

registryClient.refreshRegistryCache(output);

Path configYaml;
if (registryClient.getConfigArg() == null) {
configYaml = RegistriesConfigLocator.locateConfigYaml();
if (configYaml == null) {
configYaml = RegistriesConfigLocator.getDefaultConfigYamlLocation();
}
} else {
configYaml = Paths.get(registryClient.getConfigArg());
}

final RegistriesConfig config;
if (Files.exists(configYaml)) {
config = RegistriesConfigMapperHelper.deserialize(configYaml, JsonRegistriesConfig.class);
} else {
config = new JsonRegistriesConfig();
}

final Set<String> existingIds = config.getRegistries().stream().map(RegistryConfig::getId).collect(Collectors.toSet());
boolean persist = false;
for (String registryId : registryIds.split(",")) {
if (existingIds.add(registryId)) {
persist = true;
final JsonRegistryConfig registry = new JsonRegistryConfig();
registry.setId(registryId);
config.getRegistries().add(registry);
output.info("Registry " + registryId + " was added");
} else {
output.info("Registry " + registryId + " was skipped since it is already present");
}
}

if (persist) {
RegistriesConfigMapperHelper.serialize(config, configYaml);
}

return CommandLine.ExitCode.OK;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class RegistryListCommand extends BaseRegistryCommand {
public Integer call() throws Exception {

registryClient.refreshRegistryCache(output);
final RegistriesConfig config = RegistriesConfigLocator.resolveConfig();
final RegistriesConfig config = registryClient.resolveConfig();

final ExtensionCatalogResolver catalogResolver = streams ? registryClient.getExtensionCatalogResolver(output) : null;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package io.quarkus.cli;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;

import io.quarkus.cli.registry.BaseRegistryCommand;
import io.quarkus.cli.registry.RegistryClientMixin;
import io.quarkus.registry.config.RegistriesConfig;
import io.quarkus.registry.config.RegistriesConfigLocator;
import io.quarkus.registry.config.RegistryConfig;
import io.quarkus.registry.config.json.JsonRegistriesConfig;
import io.quarkus.registry.config.json.RegistriesConfigMapperHelper;
import picocli.CommandLine;

@CommandLine.Command(name = "remove", sortOptions = false, showDefaultValues = true, mixinStandardHelpOptions = false, header = "Remove a Quarkus extension registry from the registry client configuration", description = "%n"
+ "This command will remove a Quarkus extension registry from the registry client configuration", headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", parameterListHeading = "%n", optionListHeading = "Options:%n")
public class RegistryRemoveCommand extends BaseRegistryCommand {

@CommandLine.Mixin
protected RegistryClientMixin registryClient;

@CommandLine.Parameters(arity = "0..1", paramLabel = "REGISTRY-ID[,REGISTRY-ID]", description = "Registry ID to remove from the registry client configuration%n"
+ " Example:%n"
+ " registry.quarkus.io%n"
+ " registry.quarkus.acme.com,registry.quarkus.io%n")
String registryIds;

@Override
public Integer call() throws Exception {

registryClient.refreshRegistryCache(output);

Path configYaml;
if (registryClient.getConfigArg() == null) {
configYaml = RegistriesConfigLocator.locateConfigYaml();
if (configYaml == null) {
output.error("Failed to locate the registry client configuration file");
return CommandLine.ExitCode.SOFTWARE;
}
} else {
configYaml = Paths.get(registryClient.getConfigArg());
}

final RegistriesConfig config = RegistriesConfigMapperHelper.deserialize(configYaml, JsonRegistriesConfig.class);

final Map<String, RegistryConfig> registries = new LinkedHashMap<>(config.getRegistries().size());
config.getRegistries().forEach(r -> registries.put(r.getId(), r));
boolean persist = false;
for (String registryId : registryIds.split(",")) {
if (registries.remove(registryId) == null) {
output.info("Registry " + registryId + " was not previously configured");
} else {
output.info("Registry " + registryId + " was removed");
persist = true;
}
}

if (persist) {
final JsonRegistriesConfig jsonConfig = new JsonRegistriesConfig();
jsonConfig.setRegistries(new ArrayList<>(registries.values()));
RegistriesConfigMapperHelper.serialize(jsonConfig, configYaml);
}

return CommandLine.ExitCode.OK;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,9 @@ void setGradleProperties(ArrayDeque<String> args, boolean batchMode) {
}
args.add(registryClient.getRegistryClientProperty());

final String configFile = System.getProperty(RegistriesConfigLocator.CONFIG_FILE_PATH_PROPERTY);
final String configFile = registryClient.getConfigArg() == null
? System.getProperty(RegistriesConfigLocator.CONFIG_FILE_PATH_PROPERTY)
: registryClient.getConfigArg();
if (configFile != null) {
args.add("-D" + RegistriesConfigLocator.CONFIG_FILE_PATH_PROPERTY + "=" + configFile);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import io.quarkus.devtools.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.BuildTool;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.devtools.project.QuarkusProjectHelper;
import io.quarkus.devtools.project.buildfile.MavenProjectBuildFile;
import picocli.CommandLine;

Expand Down Expand Up @@ -75,6 +76,7 @@ public BuildTool getBuildTool() {
}

QuarkusProject quarkusProject() throws Exception {
QuarkusProjectHelper.setToolsConfig(registryClient.resolveConfig());
return MavenProjectBuildFile.getProject(projectRoot, output, Version::clientVersion);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.cli.registry;

import java.nio.file.Path;
import java.nio.file.Paths;

import io.quarkus.cli.Version;
import io.quarkus.cli.common.OutputOptionMixin;
Expand All @@ -14,6 +15,8 @@
import io.quarkus.registry.ExtensionCatalogResolver;
import io.quarkus.registry.RegistryResolutionException;
import io.quarkus.registry.catalog.ExtensionCatalog;
import io.quarkus.registry.config.RegistriesConfig;
import io.quarkus.registry.config.RegistriesConfigLocator;
import picocli.CommandLine;

public class RegistryClientMixin {
Expand All @@ -28,10 +31,21 @@ public final String getRegistryClientProperty() {
"--refresh" }, description = "Refresh the local Quarkus extension registry cache", defaultValue = "false")
boolean refresh = false;

@CommandLine.Option(paramLabel = "CONFIG", names = { "--config" }, description = "Configuration file")
String config;

public boolean enabled() {
return true;
}

public String getConfigArg() {
return config;
}

public RegistriesConfig resolveConfig() {
return config == null ? RegistriesConfigLocator.resolveConfig() : RegistriesConfigLocator.load(Paths.get(config));
}

public QuarkusProject createQuarkusProject(Path projectRoot, TargetQuarkusVersionGroup targetVersion, BuildTool buildTool,
OutputOptionMixin log) throws RegistryResolutionException {
ExtensionCatalog catalog = getExtensionCatalog(targetVersion, log);
Expand All @@ -46,6 +60,9 @@ ExtensionCatalog getExtensionCatalog(TargetQuarkusVersionGroup targetVersion, Ou
throws RegistryResolutionException {
log.debug("Resolving Quarkus extension catalog for " + targetVersion);
QuarkusProjectHelper.setMessageWriter(log);
if (enabled()) {
QuarkusProjectHelper.setToolsConfig(resolveConfig());
}

if (VALIDATE && targetVersion.isStreamSpecified() && !enabled()) {
throw new UnsupportedOperationException(
Expand Down
65 changes: 65 additions & 0 deletions devtools/cli/src/test/java/io/quarkus/cli/CliNonProjectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
import org.junit.jupiter.api.Test;

import io.quarkus.devtools.testing.RegistryClientTestHelper;
import io.quarkus.registry.config.RegistriesConfig;
import io.quarkus.registry.config.RegistriesConfigLocator;
import io.quarkus.registry.config.json.JsonRegistriesConfig;
import io.quarkus.registry.config.json.RegistriesConfigMapperHelper;
import picocli.CommandLine;

public class CliNonProjectTest {
Expand Down Expand Up @@ -200,6 +204,67 @@ public void testRegistryRefresh() throws Exception {
"Should contain '- registry.quarkus.io', found: " + result.stdout);
}

@Test
public void testRegistryAddRemove() throws Exception {

CliDriver.Result result;

final Path testConfigYaml = workspaceRoot.resolve("test-registry-add-remove.yaml").toAbsolutePath();
Files.deleteIfExists(testConfigYaml);

assertThat(testConfigYaml).doesNotExist();
result = CliDriver.execute(workspaceRoot, "registry", "add", "one,two", "--config", testConfigYaml.toString());
Assertions.assertEquals(CommandLine.ExitCode.OK, result.exitCode,
"Expected OK return code." + result);

assertThat(testConfigYaml).exists();
RegistriesConfig testConfig = RegistriesConfigLocator.load(testConfigYaml);
assertThat(testConfig.getRegistries()).hasSize(2);
assertThat(testConfig.getRegistries().get(0).getId()).isEqualTo("one");
assertThat(testConfig.getRegistries().get(1).getId()).isEqualTo("two");

result = CliDriver.execute(workspaceRoot, "registry", "add", "two,three", "--config", testConfigYaml.toString());
Assertions.assertEquals(CommandLine.ExitCode.OK, result.exitCode,
"Expected OK return code." + result);

testConfig = RegistriesConfigLocator.load(testConfigYaml);
assertThat(testConfig.getRegistries()).hasSize(3);
assertThat(testConfig.getRegistries().get(0).getId()).isEqualTo("one");
assertThat(testConfig.getRegistries().get(1).getId()).isEqualTo("two");
assertThat(testConfig.getRegistries().get(2).getId()).isEqualTo("three");

result = CliDriver.execute(workspaceRoot, "registry", "remove", "one,two", "--config", testConfigYaml.toString());
Assertions.assertEquals(CommandLine.ExitCode.OK, result.exitCode,
"Expected OK return code." + result);

testConfig = RegistriesConfigLocator.load(testConfigYaml);
assertThat(testConfig.getRegistries()).hasSize(1);
assertThat(testConfig.getRegistries().get(0).getId()).isEqualTo("three");

result = CliDriver.execute(workspaceRoot, "registry", "add", "four", "--config", testConfigYaml.toString());
Assertions.assertEquals(CommandLine.ExitCode.OK, result.exitCode,
"Expected OK return code." + result);

testConfig = RegistriesConfigLocator.load(testConfigYaml);
assertThat(testConfig.getRegistries()).hasSize(2);
assertThat(testConfig.getRegistries().get(0).getId()).isEqualTo("three");
assertThat(testConfig.getRegistries().get(1).getId()).isEqualTo("four");

result = CliDriver.execute(workspaceRoot, "registry", "remove", "three,four,five", "--config",
testConfigYaml.toString());
Assertions.assertEquals(CommandLine.ExitCode.OK, result.exitCode,
"Expected OK return code." + result);

testConfig = RegistriesConfigMapperHelper.deserialize(testConfigYaml, JsonRegistriesConfig.class);
assertThat(testConfig.getRegistries()).isEmpty();

testConfig = RegistriesConfigLocator.load(testConfigYaml);
assertThat(testConfig.getRegistries()).hasSize(1);
assertThat(testConfig.getRegistries().get(0).getId()).isEqualTo("registry.quarkus.io");

Files.delete(testConfigYaml);
}

private static String getRequiredProperty(String name) {
return Objects.requireNonNull(System.getProperty(name));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ public static RegistriesConfig toolsConfig() {
return toolsConfig == null ? toolsConfig = RegistriesConfigLocator.resolveConfig() : toolsConfig;
}

public static void setToolsConfig(RegistriesConfig config) {
toolsConfig = config;
}

public static void reset() {
initRegistryClientEnabled();
toolsConfig = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ public static RegistriesConfig load(Reader configYaml) {
}
}

/**
* Returns the registry client configuration file or null, if the file could not be found.
*
* @return the registry client configuration file or null, if the file could not be found
*/
public static Path locateConfigYaml() {
final String prop = PropertiesUtil.getProperty(CONFIG_FILE_PATH_PROPERTY);
Path configYaml;
Expand All @@ -120,10 +125,19 @@ public static Path locateConfigYaml() {
if (Files.exists(configYaml)) {
return configYaml;
}
configYaml = Paths.get(PropertiesUtil.getProperty("user.home")).resolve(CONFIG_RELATIVE_PATH);
configYaml = getDefaultConfigYamlLocation();
return Files.exists(configYaml) ? configYaml : null;
}

/**
* Returns the default location of the registry client configuration file.
*
* @return the default location of the registry client configuration file
*/
public static Path getDefaultConfigYamlLocation() {
return Paths.get(PropertiesUtil.getProperty("user.home")).resolve(CONFIG_RELATIVE_PATH);
}

static RegistriesConfig completeRequiredConfig(RegistriesConfig original) {
final JsonRegistriesConfig config = new JsonRegistriesConfig();
config.setDebug(original.isDebug());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
import io.quarkus.registry.config.RegistriesConfig;
import io.quarkus.registry.config.RegistryConfig;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

@JsonInclude(JsonInclude.Include.NON_DEFAULT)
public class JsonRegistriesConfig implements RegistriesConfig {

private boolean debug;
private List<RegistryConfig> registries = Collections.emptyList();
private List<RegistryConfig> registries = new ArrayList<>();

@Override
@JsonDeserialize(contentUsing = JsonRegistryConfigDeserializer.class)
Expand All @@ -25,13 +24,14 @@ public List<RegistryConfig> getRegistries() {
}

public void setRegistries(List<RegistryConfig> registries) {
this.registries = registries == null ? Collections.emptyList() : registries;
if (registries == null) {
this.registries.clear();
} else {
this.registries = registries;
}
}

public void addRegistry(RegistryConfig registry) {
if (registries.isEmpty()) {
registries = new ArrayList<>();
}
registries.add(registry);
}

Expand Down
Loading

0 comments on commit e85aab6

Please sign in to comment.