You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vk...@apache.org on 2020/12/26 22:39:56 UTC
[ignite-3] branch ignite-3.0.0-alpha1 updated: IGNITE-13905 Support
of cli extensions inside mvn modules (#18)
This is an automated email from the ASF dual-hosted git repository.
vkulichenko pushed a commit to branch ignite-3.0.0-alpha1
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/ignite-3.0.0-alpha1 by this push:
new 7ed18c5 IGNITE-13905 Support of cli extensions inside mvn modules (#18)
7ed18c5 is described below
commit 7ed18c5367eb4c2ae10a34f36809c5123c0c44d1
Author: Kirill Gusakov <kg...@gmail.com>
AuthorDate: Sun Dec 27 01:35:35 2020 +0300
IGNITE-13905 Support of cli extensions inside mvn modules (#18)
---
.../cli/builtins/module/MavenArtifactResolver.java | 24 ++++-
.../ignite/cli/builtins/module/ModuleManager.java | 34 ++++++-
.../ignite/cli/builtins/module/ModuleStorage.java | 11 ++
.../apache/ignite/cli/IgniteCliInterfaceTest.java | 17 ++++
.../cli/builtins/init/InitIgniteCommandTest.java | 20 ++++
.../ignite/cli/builtins/init/ModuleMangerTest.java | 112 +++++++++++++++++++++
6 files changed, 212 insertions(+), 6 deletions(-)
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/MavenArtifactResolver.java b/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/MavenArtifactResolver.java
index 809d1ef..8f2cc47 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/MavenArtifactResolver.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/MavenArtifactResolver.java
@@ -63,6 +63,8 @@ public class MavenArtifactResolver {
private final SystemPathResolver pathResolver;
private PrintWriter out;
+ private static final String FILE_ARTIFACT_PATTERN = "[artifact](-[classifier]).[revision].[ext]";
+
@Inject
public MavenArtifactResolver(SystemPathResolver pathResolver) {
this.pathResolver = pathResolver;
@@ -126,7 +128,7 @@ public class MavenArtifactResolver {
new RetrieveOptions()
// this is from the envelop module
.setConfs(new String[]{"default"})
- .setDestArtifactPattern(mavenRoot.toFile().getAbsolutePath() + "/[artifact](-[classifier]).[revision].[ext]")
+ .setDestArtifactPattern(mavenRoot.resolve("[artifact](-[classifier]).[revision].[ext]").toFile().getAbsolutePath())
);
return new ResolveResult(
@@ -140,6 +142,24 @@ public class MavenArtifactResolver {
}
}
+ /**
+ * Get artifact file name by artifactId and version
+ *
+ * Note: Current implementation doesn't support artifacts with classifiers or non-jar packaging
+ * @param artfactId
+ * @param version
+ * @return
+ */
+ public static String fileNameByArtifactPattern(
+ String artfactId,
+ String version) {
+ return FILE_ARTIFACT_PATTERN
+ .replace("[artifact]", artfactId)
+ .replace("(-[classifier])", "")
+ .replace("[revision]", version)
+ .replace("[ext]", "jar");
+ }
+
private Ivy ivyInstance(List<URL> repositories) {
File tmpDir = null;
try {
@@ -158,7 +178,7 @@ public class MavenArtifactResolver {
IvySettings ivySettings = new IvySettings();
ivySettings.setDefaultCache(tmpDir);
- ivySettings.setDefaultCacheArtifactPattern("[artifact](-[classifier]).[revision].[ext]");
+ ivySettings.setDefaultCacheArtifactPattern(FILE_ARTIFACT_PATTERN);
ChainResolver chainResolver = new ChainResolver();
chainResolver.setName("chainResolver");
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleManager.java b/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleManager.java
index 823fe22..5fa9758 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleManager.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleManager.java
@@ -17,13 +17,16 @@
package org.apache.ignite.cli.builtins.module;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.jar.JarInputStream;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -44,6 +47,7 @@ public class ModuleManager {
private final List<StandardModuleDefinition> modules;
public static final String INTERNAL_MODULE_PREFIX = "_";
+ public static final String CLI_MODULE_MANIFEST_HEADER = "Apache-Ignite-CLI-Module";
private PrintWriter out;
private ColorScheme cs;
@@ -85,10 +89,11 @@ public class ModuleManager {
String mvnName = String.join(":", mavenCoordinates.groupId,
mavenCoordinates.artifactId, mavenCoordinates.version);
+ var isCliModule = isRootArtifactCliModule(mavenCoordinates.artifactId, mavenCoordinates.version, resolveResult.artifacts());
moduleStorage.saveModule(new ModuleStorage.ModuleDefinition(
mvnName,
- resolveResult.artifacts(),
- new ArrayList<>(),
+ (isCliModule)? Collections.emptyList() : resolveResult.artifacts(),
+ (isCliModule)? resolveResult.artifacts() : Collections.emptyList(),
ModuleStorage.SourceType.Maven,
name
));
@@ -174,12 +179,23 @@ public class ModuleManager {
return modules;
}
+ private boolean isRootArtifactCliModule(String artifactId, String version, List<Path> artifacts) throws IOException {
+ var rootJarArtifactOpt = artifacts.stream()
+ .filter(p -> MavenArtifactResolver.fileNameByArtifactPattern(artifactId, version).equals(p.getFileName().toString()))
+ .findFirst();
+ if (rootJarArtifactOpt.isPresent()) {
+ try (var input = new FileInputStream(rootJarArtifactOpt.get().toFile())) {
+ var jarStream = new JarInputStream(input);
+ var manifest = jarStream.getManifest();
+ return "true".equals(manifest.getMainAttributes().getValue(CLI_MODULE_MANIFEST_HEADER));
+ }
+ } else return false;
+ }
+
private boolean isStandardModuleName(String name) {
return readBuiltinModules().stream().anyMatch(m -> m.name.equals(name));
}
-
-
private static List<StandardModuleDefinition> readBuiltinModules() {
com.typesafe.config.ConfigObject config = ConfigFactory.load("builtin_modules.conf").getObject("modules");
List<StandardModuleDefinition> modules = new ArrayList<>();
@@ -195,4 +211,14 @@ public class ModuleManager {
return modules;
}
+ private static class IgniteArtifacts {
+ private List<Path> serverArtifacts;
+ private List<Path> cliArtifacts;
+
+ public IgniteArtifacts(List<Path> serverArtifacts, List<Path> cliArtifacts) {
+ this.serverArtifacts = serverArtifacts;
+ this.cliArtifacts = cliArtifacts;
+ }
+ }
+
}
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleStorage.java b/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleStorage.java
index 1e953ca..c8fb456 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleStorage.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleStorage.java
@@ -95,6 +95,17 @@ public class ModuleStorage {
public static class ModuleDefinition {
public final String name;
public final List<Path> artifacts;
+
+ @Override public String toString() {
+ return "ModuleDefinition{" +
+ "name='" + name + '\'' +
+ ", artifacts=" + artifacts +
+ ", cliArtifacts=" + cliArtifacts +
+ ", type=" + type +
+ ", source='" + source + '\'' +
+ '}';
+ }
+
public final List<Path> cliArtifacts;
public final SourceType type;
public final String source;
diff --git a/modules/cli/src/test/java/org/apache/ignite/cli/IgniteCliInterfaceTest.java b/modules/cli/src/test/java/org/apache/ignite/cli/IgniteCliInterfaceTest.java
index 7703307..498df94 100644
--- a/modules/cli/src/test/java/org/apache/ignite/cli/IgniteCliInterfaceTest.java
+++ b/modules/cli/src/test/java/org/apache/ignite/cli/IgniteCliInterfaceTest.java
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.ignite.cli;
import java.io.ByteArrayOutputStream;
diff --git a/modules/cli/src/test/java/org/apache/ignite/cli/builtins/init/InitIgniteCommandTest.java b/modules/cli/src/test/java/org/apache/ignite/cli/builtins/init/InitIgniteCommandTest.java
index 52aa308..0c2c10e 100644
--- a/modules/cli/src/test/java/org/apache/ignite/cli/builtins/init/InitIgniteCommandTest.java
+++ b/modules/cli/src/test/java/org/apache/ignite/cli/builtins/init/InitIgniteCommandTest.java
@@ -1,7 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.ignite.cli.builtins.init;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
@@ -9,6 +27,7 @@ import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.jar.Manifest;
import javax.inject.Inject;
import io.micronaut.test.annotation.MockBean;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
@@ -22,6 +41,7 @@ import org.junit.jupiter.api.io.TempDir;
import org.mockito.junit.jupiter.MockitoExtension;
import picocli.CommandLine.Help.ColorScheme;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
diff --git a/modules/cli/src/test/java/org/apache/ignite/cli/builtins/init/ModuleMangerTest.java b/modules/cli/src/test/java/org/apache/ignite/cli/builtins/init/ModuleMangerTest.java
new file mode 100644
index 0000000..130c294
--- /dev/null
+++ b/modules/cli/src/test/java/org/apache/ignite/cli/builtins/init/ModuleMangerTest.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cli.builtins.init;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.jar.Attributes;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import javax.inject.Inject;
+import io.micronaut.test.annotation.MockBean;
+import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
+import org.apache.ignite.cli.IgnitePaths;
+import org.apache.ignite.cli.builtins.module.MavenArtifactResolver;
+import org.apache.ignite.cli.builtins.module.ModuleManager;
+import org.apache.ignite.cli.builtins.module.ModuleStorage;
+import org.apache.ignite.cli.builtins.module.ResolveResult;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.junit.jupiter.MockitoExtension;
+import picocli.CommandLine;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@MicronautTest
+public class ModuleMangerTest {
+
+ @Inject MavenArtifactResolver mavenArtifactResolver;
+ @Inject ModuleManager moduleManager;
+ @Inject ModuleStorage moduleStorage;
+
+ @TempDir Path artifactsDir;
+ @TempDir Path homeDir;
+
+ @Test
+ void testCliModuleInstallation() throws IOException {
+ var rootArtifact = generateJar("test-module", "1.0", true);
+ var depArtifact = generateJar("dep-artifact", "0.1", false);
+ when(mavenArtifactResolver.resolve(any(), any(), any(), any(), any())).thenReturn(
+ new ResolveResult(Arrays.asList(rootArtifact, depArtifact)));
+
+ var ignitePaths = new IgnitePaths(homeDir.resolve("bin"), homeDir.resolve("work"), "n/a");
+ moduleManager.setOut(new PrintWriter(System.out));
+ moduleManager.setColorScheme(CommandLine.Help.defaultColorScheme(CommandLine.Help.Ansi.AUTO));
+ moduleManager.addModule("mvn:any-group:test-module:1.0", ignitePaths, Collections.emptyList());
+
+ verify(moduleStorage).saveModule(argThat(m ->
+ m.cliArtifacts.equals(Arrays.asList(rootArtifact, depArtifact)) &&
+ m.artifacts.equals(Collections.emptyList())));
+ }
+
+ @Test
+ void testServerModuleInstallation() throws IOException {
+ var rootArtifact = generateJar("test-module", "1.0", false);
+ var depArtifact = generateJar("dep-artifact", "0.1", false);
+ when(mavenArtifactResolver.resolve(any(), any(), any(), any(), any())).thenReturn(
+ new ResolveResult(Arrays.asList(rootArtifact, depArtifact)));
+
+ var ignitePaths = new IgnitePaths(homeDir.resolve("bin"), homeDir.resolve("work"), "n/a");
+ moduleManager.setOut(new PrintWriter(System.out));
+ moduleManager.setColorScheme(CommandLine.Help.defaultColorScheme(CommandLine.Help.Ansi.AUTO));
+ moduleManager.addModule("mvn:any-group:test-module:1.0", ignitePaths, Collections.emptyList());
+
+ verify(moduleStorage).saveModule(argThat(m ->
+ m.artifacts.equals(Arrays.asList(rootArtifact, depArtifact)) &&
+ m.cliArtifacts.equals(Collections.emptyList())));
+ }
+
+ @MockBean(MavenArtifactResolver.class) MavenArtifactResolver mavenArtifactResolver() {
+ return mock(MavenArtifactResolver.class);
+ }
+
+ @MockBean(ModuleStorage.class) ModuleStorage moduleStorage() {
+ return mock(ModuleStorage.class);
+ }
+
+ private Path generateJar(String artifactId, String version, boolean isCliModule) throws IOException {
+ Manifest manifest = new Manifest();
+ manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
+ var jarPath = artifactsDir.resolve(MavenArtifactResolver.fileNameByArtifactPattern(artifactId, version));
+ if (isCliModule)
+ manifest.getMainAttributes().put(new Attributes.Name(ModuleManager.CLI_MODULE_MANIFEST_HEADER), "true");
+ var target = new JarOutputStream(new FileOutputStream(jarPath.toString()), manifest);
+ target.close();
+ return jarPath;
+ }
+}