Skip to content

Commit

Permalink
[env-manager] enable candidate to provide metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
rmannibucau committed Feb 7, 2024
1 parent 81213cb commit 2810d86
Show file tree
Hide file tree
Showing 17 changed files with 186 additions and 73 deletions.
1 change: 1 addition & 0 deletions env-manager/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
</systemPropertyVariables>
<environmentVariables>
<YEM_ORIGINAL_PATH>skip</YEM_ORIGINAL_PATH>
<CI>true</CI> <!-- no emoji for tests -->
</environmentVariables>
</configuration>
</plugin>
Expand Down
12 changes: 8 additions & 4 deletions env-manager/src/main/java/io/yupiik/dev/command/Delete.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.yupiik.dev.command;

import io.yupiik.dev.provider.ProviderRegistry;
import io.yupiik.dev.shared.MessageHelper;
import io.yupiik.fusion.framework.build.api.cli.Command;
import io.yupiik.fusion.framework.build.api.configuration.Property;
import io.yupiik.fusion.framework.build.api.configuration.RootConfiguration;
Expand All @@ -28,20 +29,23 @@ public class Delete implements Runnable {
private final Logger logger = Logger.getLogger(getClass().getName());
private final Conf conf;
private final ProviderRegistry registry;
private final MessageHelper messageHelper;

public Delete(final Conf conf,
final ProviderRegistry registry) {
final ProviderRegistry registry,
final MessageHelper messageHelper) {
this.conf = conf;
this.registry = registry;
this.messageHelper = messageHelper;
}

@Override
public void run() {
try {
registry.findByToolVersionAndProvider(conf.tool(), conf.version(), conf.provider(), false)
.thenAccept(providerAndVersion -> {
providerAndVersion.getKey().delete(conf.tool(), providerAndVersion.getValue().identifier());
logger.info(() -> "Deleted " + conf.tool() + "@" + providerAndVersion.getValue().version());
.thenAccept(matched -> {
matched.provider().delete(conf.tool(), matched.version().identifier());
logger.info(() -> "Deleted " + messageHelper.formatToolNameAndVersion(matched.candidate(), conf.tool(), matched.version().version()));
})
.toCompletableFuture()
.get();
Expand Down
26 changes: 15 additions & 11 deletions env-manager/src/main/java/io/yupiik/dev/command/Env.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.yupiik.dev.command;

import io.yupiik.dev.shared.MessageHelper;
import io.yupiik.dev.shared.Os;
import io.yupiik.dev.shared.RcService;
import io.yupiik.fusion.framework.build.api.cli.Command;
Expand Down Expand Up @@ -42,11 +43,13 @@ public class Env implements Runnable {
private final Conf conf;
private final RcService rc;
private final Os os;
private final MessageHelper messageHelper;

public Env(final Conf conf, final Os os, final RcService rc) {
public Env(final Conf conf, final Os os, final RcService rc, final MessageHelper messageHelper) {
this.conf = conf;
this.os = os;
this.rc = rc;
this.messageHelper = messageHelper;
}

@Override
Expand Down Expand Up @@ -99,28 +102,29 @@ public void close() throws SecurityException {

try {
rc.toToolProperties(tools).thenAccept(resolved -> {
final var toolVars = resolved.entrySet().stream()
final var toolVars = resolved.stream()
.flatMap(e -> Stream.of(
export + e.getKey().envPathVarName() + "=\"" + quoted(e.getValue()) + "\";",
export + e.getKey().envVersionVarName() + "=\"" + e.getKey().version() + "\";"))
export + e.properties().envPathVarName() + "=\"" + quoted(e.path()) + "\";",
export + e.properties().envVersionVarName() + "=\"" + e.properties().version() + "\";"))
.sorted()
.collect(joining("\n", "", "\n"));

final var pathBase = ofNullable(System.getenv("YEM_ORIGINAL_PATH"))
.or(() -> ofNullable(System.getenv(pathName)))
.orElse("");
final var pathVars = resolved.keySet().stream().anyMatch(RcService.ToolProperties::addToPath) ?
final var pathVars = resolved.stream().map(RcService.MatchedPath::properties).anyMatch(RcService.ToolProperties::addToPath) ?
export + "YEM_ORIGINAL_PATH=\"" + pathBase + "\";\n" +
export + pathName + "=\"" + resolved.entrySet().stream()
.filter(r -> r.getKey().addToPath())
.map(r -> quoted(rc.toBin(r.getValue())))
export + pathName + "=\"" + resolved.stream()
.filter(r -> r.properties().addToPath())
.map(r -> quoted(rc.toBin(r.path())))
.collect(joining(pathSeparator, "", pathSeparator)) + pathVar + "\";\n" :
"";
final var echos = Boolean.parseBoolean(tools.getProperty("echo", "true")) ?
resolved.entrySet().stream()
resolved.stream()
// don't log too much, if it does not change, don't re-log it
.filter(Predicate.not(it -> Objects.equals(it.getValue().toString(), System.getenv(it.getKey().envPathVarName()))))
.map(e -> "echo \"[yem] Resolved " + e.getKey().toolName() + "@" + e.getKey().version() + " to '" + e.getValue() + "'\";")
.filter(Predicate.not(it -> Objects.equals(it.path().toString(), System.getenv(it.properties().envPathVarName()))))
.map(e -> "echo \"[yem] Resolved " + messageHelper.formatToolNameAndVersion(
e.candidate(), e.properties().toolName(), e.properties().version()) + " to '" + e.path() + "'\";")
.collect(joining("\n", "", "\n")) :
"";

Expand Down
13 changes: 9 additions & 4 deletions env-manager/src/main/java/io/yupiik/dev/command/Install.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.yupiik.dev.command;

import io.yupiik.dev.provider.ProviderRegistry;
import io.yupiik.dev.shared.MessageHelper;
import io.yupiik.fusion.framework.build.api.cli.Command;
import io.yupiik.fusion.framework.build.api.configuration.Property;
import io.yupiik.fusion.framework.build.api.configuration.RootConfiguration;
Expand All @@ -31,20 +32,24 @@ public class Install implements Runnable {
private final Logger logger = Logger.getLogger(getClass().getName());
private final Conf conf;
private final ProviderRegistry registry;
private final MessageHelper messageHelper;

public Install(final Conf conf,
final ProviderRegistry registry) {
final ProviderRegistry registry,
final MessageHelper messageHelper) {
this.conf = conf;
this.registry = registry;
this.messageHelper = messageHelper;
}

@Override
public void run() {
try {
registry.findByToolVersionAndProvider(conf.tool(), conf.version(), conf.provider(), conf.relaxed())
.thenCompose(providerAndVersion -> providerAndVersion.getKey()
.install(conf.tool(), providerAndVersion.getValue().identifier(), this::onProgress)
.thenAccept(result -> logger.info(() -> "Installed " + conf.tool() + "@" + providerAndVersion.getValue().version() + " at '" + result + "'")))
.thenCompose(matched -> matched.provider()
.install(conf.tool(), matched.version().identifier(), this::onProgress)
.thenAccept(result -> logger.info(() -> "Installed " + messageHelper.formatToolNameAndVersion(
matched.candidate(), conf.tool(), matched.version().version()) + " at '" + result + "'")))
.toCompletableFuture()
.get();
} catch (final InterruptedException e) {
Expand Down
12 changes: 8 additions & 4 deletions env-manager/src/main/java/io/yupiik/dev/command/Resolve.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.yupiik.dev.command;

import io.yupiik.dev.provider.ProviderRegistry;
import io.yupiik.dev.shared.MessageHelper;
import io.yupiik.fusion.framework.build.api.cli.Command;
import io.yupiik.fusion.framework.build.api.configuration.Property;
import io.yupiik.fusion.framework.build.api.configuration.RootConfiguration;
Expand All @@ -28,21 +29,24 @@ public class Resolve implements Runnable {
private final Logger logger = Logger.getLogger(getClass().getName());
private final Conf conf;
private final ProviderRegistry registry;
private final MessageHelper messageHelper;

public Resolve(final Conf conf,
final ProviderRegistry registry) {
final ProviderRegistry registry,
final MessageHelper messageHelper) {
this.conf = conf;
this.registry = registry;
this.messageHelper = messageHelper;
}

@Override
public void run() {
try {
registry.findByToolVersionAndProvider(conf.tool(), conf.version(), conf.provider(), false)
.thenAccept(providerAndVersion -> {
final var resolved = providerAndVersion.getKey().resolve(conf.tool(), providerAndVersion.getValue().identifier())
.thenAccept(matched -> {
final var resolved = matched.provider().resolve(conf.tool(), matched.version().identifier())
.orElseThrow(() -> new IllegalArgumentException("No matching instance for " + conf.tool() + "@" + conf.version() + ", ensure to install it before resolving it."));
logger.info(() -> "Resolved " + conf.tool() + "@" + providerAndVersion.getValue().version() + ": '" + resolved + "'");
logger.info(() -> "Resolved " + messageHelper.formatToolNameAndVersion(matched.candidate(), conf.tool(), matched.version().version()) + ": '" + resolved + "'");
})
.toCompletableFuture()
.get();
Expand Down
18 changes: 9 additions & 9 deletions env-manager/src/main/java/io/yupiik/dev/command/Run.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,17 @@ public void run() {
}
}

private void setEnv(final Map<RcService.ToolProperties, Path> resolved, final Map<String, String> environment) {
resolved.forEach((tool, home) -> {
final var homeStr = home.toString();
logger.finest(() -> "Setting '" + tool.envPathVarName() + "' to '" + homeStr + "'");
environment.put(tool.envPathVarName(), homeStr);
private void setEnv(final List<RcService.MatchedPath> resolved, final Map<String, String> environment) {
resolved.forEach(it -> {
final var homeStr = it.path().toString();
logger.finest(() -> "Setting '" + it.properties().envPathVarName() + "' to '" + homeStr + "'");
environment.put(it.properties().envPathVarName(), homeStr);
});
if (resolved.keySet().stream().anyMatch(RcService.ToolProperties::addToPath)) {
if (resolved.stream().map(RcService.MatchedPath::properties).anyMatch(RcService.ToolProperties::addToPath)) {
final var pathName = os.isWindows() ? "Path" : "PATH";
final var path = resolved.entrySet().stream()
.filter(r -> r.getKey().addToPath())
.map(r -> rc.toBin(r.getValue()).toString())
final var path = resolved.stream()
.filter(r -> r.properties().addToPath())
.map(r -> rc.toBin(r.path()).toString())
.collect(joining(pathSeparator, "", pathSeparator)) +
ofNullable(System.getenv(pathName)).orElse("");
logger.finest(() -> "Setting 'PATH' to '" + path + "'");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import java.util.stream.Stream;

import static java.util.Locale.ROOT;
import static java.util.Map.entry;
import static java.util.Optional.empty;
import static java.util.concurrent.CompletableFuture.completedFuture;
import static java.util.logging.Level.FINEST;
Expand Down Expand Up @@ -68,8 +67,8 @@ public List<Provider> providers() {
return providers;
}

public CompletionStage<Map.Entry<Provider, Version>> findByToolVersionAndProvider(final String tool, final String version, final String provider,
final boolean relaxed) {
public CompletionStage<MatchedVersion> findByToolVersionAndProvider(final String tool, final String version, final String provider,
final boolean relaxed) {
return tryFindByToolVersionAndProvider(tool, version, provider, relaxed, new Cache(new ConcurrentHashMap<>(), new ConcurrentHashMap<>()))
.thenApply(found -> found.orElseThrow(() -> new IllegalArgumentException(
"No provider for tool " + tool + "@" + version + "', available tools:\n" +
Expand Down Expand Up @@ -102,10 +101,10 @@ public CompletionStage<Map.Entry<Provider, Version>> findByToolVersionAndProvide
.collect(joining("\n")))));
}

public CompletionStage<Optional<Map.Entry<Provider, Version>>> tryFindByToolVersionAndProvider(
public CompletionStage<Optional<MatchedVersion>> tryFindByToolVersionAndProvider(
final String tool, final String version, final String provider, final boolean relaxed,
final Cache cache) {
final var result = new CompletableFuture<Optional<Map.Entry<Provider, Version>>>();
final var result = new CompletableFuture<Optional<MatchedVersion>>();
final var promises = providers().stream()
.filter(it -> provider == null ||
// enable "--install-provider zulu" for example
Expand All @@ -127,7 +126,13 @@ public CompletionStage<Optional<Map.Entry<Provider, Version>>> tryFindByToolVers
.thenApply(all -> all.stream()
.filter(v -> matchVersion(v, version, relaxed))
.findFirst()
.map(v -> entry(it, v)))
.map(v -> new MatchedVersion(
it,
candidates.stream()
.filter(c -> Objects.equals(c.tool(), tool))
.findFirst()
.orElse(null),
v)))
.toCompletableFuture()));
}
return completedFuture(Optional.empty());
Expand Down Expand Up @@ -169,15 +174,16 @@ private CompletionStage<List<Version>> findRemoteVersions(final String tool, fin
}));
}

private Stream<Map.Entry<Provider, Version>> findMatchingVersion(final String tool, final String version,
final boolean relaxed, final Provider provider,
final Map<Candidate, List<Version>> versions) {
private Stream<MatchedVersion> findMatchingVersion(final String tool, final String version,
final boolean relaxed, final Provider provider,
final Map<Candidate, List<Version>> versions) {
return versions.entrySet().stream()
.filter(e -> Objects.equals(e.getKey().tool(), tool))
.flatMap(e -> e.getValue().stream().filter(v -> matchVersion(v, version, relaxed)))
.findFirst()
.stream()
.map(v -> entry(provider, v));
.flatMap(e -> e.getValue().stream()
.filter(v -> matchVersion(v, version, relaxed))
.findFirst()
.stream()
.map(v -> new MatchedVersion(provider, e.getKey(), v)));
}

private boolean matchVersion(final Version v, final String version, final boolean relaxed) {
Expand All @@ -188,4 +194,7 @@ private boolean matchVersion(final Version v, final String version, final boolea
public record Cache(Map<Provider, Map<Candidate, List<Version>>> local,
Map<Provider, Map<String, List<Version>>> versions) {
}

public record MatchedVersion(Provider provider, Candidate candidate, Version version) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,23 @@ public class CentralBaseProvider implements Provider {
private final Gav gav;
private final Path local;
private final boolean enabled;
private final Map<String, String> meta;

public CentralBaseProvider(final YemHttpClient client,
final CentralConfiguration conf, // children must use SingletonCentralConfiguration to avoid multiple creations
final Archives archives,
final Cache cache,
final Gav gav,
final boolean enabled) {
final boolean enabled,
final Map<String, String> meta) {
this.client = client;
this.archives = archives;
this.cache = cache;
this.base = URI.create(conf.base());
this.local = Path.of(conf.local());
this.gav = gav;
this.enabled = enabled;
this.meta = meta;
}

public Gav gav() {
Expand Down Expand Up @@ -185,7 +188,7 @@ public CompletionStage<List<Candidate>> listTools() {

return completedFuture(List.of(new Candidate(
gav.artifactId().startsWith("apache-") ? gav.artifactId().substring("apache-".length()) : gavString,
toName(gav.artifactId()), gavString + " downloaded from central.", base.toASCIIString())));
toName(gav.artifactId()), gavString + " downloaded from central.", base.toASCIIString(), meta)));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import io.yupiik.fusion.framework.build.api.event.OnEvent;
import io.yupiik.fusion.framework.build.api.order.Order;

import java.util.Map;

@ApplicationScoped
public class CentralProviderInit {
public void onStart(@OnEvent @Order(Integer.MIN_VALUE + 100) final Start start,
Expand All @@ -40,7 +42,10 @@ public void onStart(@OnEvent @Order(Integer.MIN_VALUE + 100) final Start start,
final var beans = container.getBeans();
registry.gavs().forEach(gav -> beans.doRegister(new ProvidedInstanceBean<>(DefaultScoped.class, CentralBaseProvider.class, () -> {
final var enabled = "true".equals(conf.get(gav.artifactId() + ".enabled").orElse("true"));
return new CentralBaseProvider(client, configuration, archives, cache, gav, enabled);
return new CentralBaseProvider(client, configuration, archives, cache, gav, enabled, switch (gav.artifactId()) {
case "apache-maven" -> Map.of("emoji", "\uD83E\uDD89");
default -> Map.of();
});
})));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ public CompletionStage<List<Candidate>> listTools() {
return completedFuture(List.of());
}
return completedFuture(List.of(new Candidate(
"minikube", "Minikube", "Local development Kubernetes binary.", "https://minikube.sigs.k8s.io/docs/")));
"minikube", "Minikube", "Local development Kubernetes binary.", "https://minikube.sigs.k8s.io/docs/",
Map.of("emoji", "☸️"))));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@
*/
package io.yupiik.dev.provider.model;

public record Candidate(String tool, String name, String description, String url) {
import java.util.Map;

public record Candidate(String tool, String name, String description, String url, Map<String, String> metadata) {
}
Loading

0 comments on commit 2810d86

Please sign in to comment.