Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI add/remove registry commands #19619

Merged
merged 1 commit into from
Aug 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
ebullient marked this conversation as resolved.
Show resolved Hide resolved
? 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