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/23 18:31:09 UTC
[ignite-3] branch main updated: IGNITE-13782 Add reinit support for
corrupted installation (#11)
This is an automated email from the ASF dual-hosted git repository.
vkulichenko pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new fad5da0 IGNITE-13782 Add reinit support for corrupted installation (#11)
fad5da0 is described below
commit fad5da092fabca218843682195e7cf8cab7947d6
Author: Kirill Gusakov <kg...@gmail.com>
AuthorDate: Wed Dec 23 21:30:59 2020 +0300
IGNITE-13782 Add reinit support for corrupted installation (#11)
---
modules/cli-demo/cli/pom.xml | 6 ++
.../apache/ignite/cli/CliPathsConfigLoader.java | 25 +++---
.../java/org/apache/ignite/cli/IgnitePaths.java | 24 ++++++
.../cli/builtins/init/InitIgniteCommand.java | 65 +++++----------
.../ignite/cli/builtins/module/ModuleStorage.java | 7 +-
.../cli/builtins/init/InitIgniteCommandTest.java | 93 ++++++++++++++++++++++
.../cli/src/test/resources/builtin_modules.conf | 13 +++
.../cli/src/test/resources/logback-test.xml | 14 ++++
.../cli/src/test/resources/version.properties | 18 +++++
9 files changed, 208 insertions(+), 57 deletions(-)
diff --git a/modules/cli-demo/cli/pom.xml b/modules/cli-demo/cli/pom.xml
index 59b458e..90b92ca 100644
--- a/modules/cli-demo/cli/pom.xml
+++ b/modules/cli-demo/cli/pom.xml
@@ -83,6 +83,12 @@
<version>3.3.3</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>io.micronaut.test</groupId>
+ <artifactId>micronaut-test-junit5</artifactId>
+ <version>2.1.1</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>io.micronaut</groupId>
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/CliPathsConfigLoader.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/CliPathsConfigLoader.java
index 794086a..7db5bb5 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/CliPathsConfigLoader.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/CliPathsConfigLoader.java
@@ -17,7 +17,6 @@
package org.apache.ignite.cli;
-import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -42,28 +41,30 @@ public class CliPathsConfigLoader {
}
public Optional<IgnitePaths> loadIgnitePathsConfig() {
- return searchConfigPathsFile()
- .map(f -> CliPathsConfigLoader.readConfigFile(f, version));
+ if (configFilePath().toFile().exists())
+ return Optional.of(CliPathsConfigLoader.readConfigFile(configFilePath(), version));
+
+ return Optional.empty();
}
public IgnitePaths loadIgnitePathsOrThrowError() {
Optional<IgnitePaths> ignitePaths = loadIgnitePathsConfig();
- if (ignitePaths.isPresent())
+ if (ignitePaths.isPresent()) {
+ if (!ignitePaths.get().validateDirs())
+ throw new IgniteCLIException("Some required directories are absent. " +
+ "Try to run 'init' command to fix the issue.");
return ignitePaths.get();
+ }
else
throw new IgniteCLIException("To execute node module/node management commands you must run 'init' first");
}
- public Optional<File> searchConfigPathsFile() {
- File homeDirCfg = pathResolver.osHomeDirectoryPath().resolve(".ignitecfg").toFile();
- if (homeDirCfg.exists())
- return Optional.of(homeDirCfg);
-
- return Optional.empty();
+ public Path configFilePath() {
+ return pathResolver.osHomeDirectoryPath().resolve(".ignitecfg");
}
- private static IgnitePaths readConfigFile(File configFile, String version) {
- try (InputStream inputStream = new FileInputStream(configFile)) {
+ private static IgnitePaths readConfigFile(Path configPath, String version) {
+ try (InputStream inputStream = new FileInputStream(configPath.toFile())) {
Properties properties = new Properties();
properties.load(inputStream);
if ((properties.getProperty("bin") == null) || (properties.getProperty("work") == null))
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/IgnitePaths.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/IgnitePaths.java
index 4a5ac67..3a1c440 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/IgnitePaths.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/IgnitePaths.java
@@ -17,6 +17,7 @@
package org.apache.ignite.cli;
+import java.io.File;
import java.nio.file.Path;
public class IgnitePaths {
@@ -56,5 +57,28 @@ public class IgnitePaths {
return serverConfigDir().resolve("default-config.xml");
}
+ public void initOrRecover() {
+ File igniteWork = workDir.toFile();
+ if (!(igniteWork.exists() || igniteWork.mkdirs()))
+ throw new IgniteCLIException("Can't create working directory: " + workDir);
+ File igniteBin = libsDir().toFile();
+ if (!(igniteBin.exists() || igniteBin.mkdirs()))
+ throw new IgniteCLIException("Can't create a directory for ignite modules: " + libsDir());
+
+ File igniteBinCli = cliLibsDir().toFile();
+ if (!(igniteBinCli.exists() || igniteBinCli.mkdirs()))
+ throw new IgniteCLIException("Can't create a directory for cli modules: " + cliLibsDir());
+
+ File serverConfig = serverConfigDir().toFile();
+ if (!(serverConfig.exists() || serverConfig.mkdirs()))
+ throw new IgniteCLIException("Can't create a directory for server configs: " + serverConfigDir());
+ }
+
+ public boolean validateDirs() {
+ return workDir.toFile().exists() &&
+ libsDir().toFile().exists() &&
+ cliLibsDir().toFile().exists() &&
+ serverConfigDir().toFile().exists();
+ }
}
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/builtins/init/InitIgniteCommand.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/builtins/init/InitIgniteCommand.java
index c3eef48..71d5a7e 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/builtins/init/InitIgniteCommand.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/builtins/init/InitIgniteCommand.java
@@ -55,59 +55,36 @@ public class InitIgniteCommand {
moduleManager.setOut(out);
Optional<IgnitePaths> ignitePathsOpt = cliPathsConfigLoader.loadIgnitePathsConfig();
if (ignitePathsOpt.isEmpty()) {
- out.println("Init ignite directories...");
- IgnitePaths ignitePaths = initDirectories(out);
- out.println("Download and install current ignite version...");
- installIgnite(ignitePaths);
- out.println("Init default Ignite configs");
- initDefaultServerConfigs();
- out.println();
- out.println("Apache Ignite version " + cliVersionInfo.version + " sucessfully installed");
- } else {
- IgnitePaths cfg = ignitePathsOpt.get();
- out.println("Apache Ignite was initialized earlier\n" +
- "Configuration file: " + cliPathsConfigLoader.searchConfigPathsFile().get() + "\n" +
- "Ignite binaries dir: " + cfg.binDir + "\n" +
- "Ignite work dir: " + cfg.workDir);
+ File cfgFile = initConfigFile();
+ out.println("Configuration file initialized: " + cfgFile);
}
+ IgnitePaths cfg = cliPathsConfigLoader.loadIgnitePathsConfig().get();
+ out.println("Init ignite directories...");
+ cfg.initOrRecover();
+ out.println("Download and install current ignite version...");
+ installIgnite(cfg);
+ out.println("Init default Ignite configs");
+ initDefaultServerConfigs(cfg.serverDefaultConfigFile());
+ out.println();
+ out.println("Apache Ignite version " + cliVersionInfo.version + " successfully installed");
+ out.println(
+ "Configuration file: " + cliPathsConfigLoader.configFilePath() + "\n" +
+ "Ignite binaries dir: " + cfg.binDir + "\n" +
+ "Ignite work dir: " + cfg.workDir);
}
- private void initDefaultServerConfigs() {
- Path serverCfgFile = cliPathsConfigLoader.loadIgnitePathsOrThrowError().serverDefaultConfigFile();
+ private void initDefaultServerConfigs(Path serverCfgFile) {
try {
- Files.copy(InitIgniteCommand.class.getResourceAsStream("/default-config.xml"), serverCfgFile);
+ if (!serverCfgFile.toFile().exists())
+ Files.copy(
+ InitIgniteCommand.class
+ .getResourceAsStream("/default-config.xml"), serverCfgFile);
}
catch (IOException e) {
- throw new IgniteCLIException("Can't create default config file for server");
+ throw new IgniteCLIException("Can't create default config file for server", e);
}
}
- private IgnitePaths initDirectories(PrintWriter out) {
- File cfgFile = initConfigFile();
- out.println("Configuration file initialized: " + cfgFile);
- IgnitePaths cfg = cliPathsConfigLoader.loadIgnitePathsOrThrowError();
- out.println("Ignite binaries dir: " + cfg.binDir);
- out.println("Ignite work dir: " + cfg.workDir);
-
- File igniteWork = cfg.workDir.toFile();
- if (!(igniteWork.exists() || igniteWork.mkdirs()))
- throw new IgniteCLIException("Can't create working directory: " + cfg.workDir);
-
- File igniteBin = cfg.libsDir().toFile();
- if (!(igniteBin.exists() || igniteBin.mkdirs()))
- throw new IgniteCLIException("Can't create a directory for ignite modules: " + cfg.libsDir());
-
- File igniteBinCli = cfg.cliLibsDir().toFile();
- if (!(igniteBinCli.exists() || igniteBinCli.mkdirs()))
- throw new IgniteCLIException("Can't create a directory for cli modules: " + cfg.cliLibsDir());
-
- File serverConfig = cfg.serverConfigDir().toFile();
- if (!(serverConfig.exists() || serverConfig.mkdirs()))
- throw new IgniteCLIException("Can't create a directory for server configs: " + cfg.serverConfigDir());
-
- return cfg;
- }
-
private void installIgnite(IgnitePaths ignitePaths) {
moduleManager.addModule("_server", ignitePaths, Collections.emptyList());
}
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleStorage.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleStorage.java
index 1219327..920b84a 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleStorage.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/builtins/module/ModuleStorage.java
@@ -29,6 +29,7 @@ import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ignite.cli.CliPathsConfigLoader;
+import org.apache.ignite.cli.IgnitePaths;
@Singleton
public class ModuleStorage {
@@ -62,7 +63,11 @@ public class ModuleStorage {
}
public ModuleDefinitionsRegistry listInstalled() throws IOException {
- if (!moduleFile().toFile().exists())
+ var moduleFileAvailable =
+ cliPathsConfigLoader.loadIgnitePathsConfig()
+ .map(p -> p.installedModulesFile().toFile().exists())
+ .orElse(false);
+ if (!moduleFileAvailable)
return new ModuleDefinitionsRegistry(new ArrayList<>());
else {
ObjectMapper objectMapper = new ObjectMapper();
diff --git a/modules/cli-demo/cli/src/test/java/org/apache/ignite/cli/builtins/init/InitIgniteCommandTest.java b/modules/cli-demo/cli/src/test/java/org/apache/ignite/cli/builtins/init/InitIgniteCommandTest.java
new file mode 100644
index 0000000..c9e708e
--- /dev/null
+++ b/modules/cli-demo/cli/src/test/java/org/apache/ignite/cli/builtins/init/InitIgniteCommandTest.java
@@ -0,0 +1,93 @@
+package org.apache.ignite.cli.builtins.init;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import javax.inject.Inject;
+import io.micronaut.test.annotation.MockBean;
+import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
+import org.apache.ignite.cli.CliPathsConfigLoader;
+import org.apache.ignite.cli.builtins.SystemPathResolver;
+import org.apache.ignite.cli.builtins.module.MavenArtifactResolver;
+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 static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@MicronautTest
+public class InitIgniteCommandTest {
+
+ @Inject SystemPathResolver pathResolver;
+ @Inject MavenArtifactResolver mavenArtifactResolver;
+ @Inject InitIgniteCommand initIgniteCommand;
+ @Inject CliPathsConfigLoader cliPathsConfigLoader;
+
+ @TempDir Path homeDir;
+ @TempDir Path currentDir;
+
+ @Test
+ void init() throws IOException {
+ when(pathResolver.osHomeDirectoryPath()).thenReturn(homeDir);
+ when(pathResolver.osCurrentDirPath()).thenReturn(currentDir);
+
+ when(mavenArtifactResolver.resolve(any(), any(), any(), any(), any()))
+ .thenReturn(new ResolveResult(Arrays.asList()));
+
+ var out = new ByteArrayOutputStream();
+ initIgniteCommand.init(new PrintWriter(System.out, true));
+
+ var ignitePaths = cliPathsConfigLoader.loadIgnitePathsConfig().get();
+ assertTrue(ignitePaths.validateDirs());
+ }
+
+ @Test
+ void reinit() throws IOException {
+ when(pathResolver.osHomeDirectoryPath()).thenReturn(homeDir);
+ when(pathResolver.osCurrentDirPath()).thenReturn(currentDir);
+
+ when(mavenArtifactResolver.resolve(any(), any(), any(), any(), any()))
+ .thenReturn(new ResolveResult(Collections.emptyList()));
+
+ var out = new PrintWriter(System.out, true);
+ initIgniteCommand.init(out);
+
+ var ignitePaths = cliPathsConfigLoader.loadIgnitePathsOrThrowError();
+ recursiveDirRemove(ignitePaths.binDir);
+
+ assertFalse(ignitePaths::validateDirs);
+
+ initIgniteCommand.init(out);
+ assertTrue(ignitePaths::validateDirs);
+ }
+
+ @MockBean(MavenArtifactResolver.class) MavenArtifactResolver mavenArtifactResolver() {
+ return mock(MavenArtifactResolver.class);
+ }
+
+ @MockBean(SystemPathResolver.class) SystemPathResolver systemPathResolver() {
+ return mock(SystemPathResolver.class);
+ }
+
+ private void recursiveDirRemove(Path dir) throws IOException {
+ Files.walk(dir)
+ .sorted(Comparator.reverseOrder())
+ .map(Path::toFile)
+ .forEach(File::delete);
+ dir.toFile().delete();
+
+ }
+}
diff --git a/modules/cli-demo/cli/src/test/resources/builtin_modules.conf b/modules/cli-demo/cli/src/test/resources/builtin_modules.conf
new file mode 100644
index 0000000..0cde1d2
--- /dev/null
+++ b/modules/cli-demo/cli/src/test/resources/builtin_modules.conf
@@ -0,0 +1,13 @@
+modules : {
+ _server: {
+ description: "Collection of base modules, which needed for start ignite server",
+ artifacts: ["mvn:org.apache.ignite:ignite-configuration-simplistic-ignite"],
+ cli-artifacts: []
+ },
+
+ ignite-demo-cli {
+ description: "Demo Ignite module with additional cli command 'snapshot'",
+ artifacts: ["mvn:org.apache.ignite:ignite-demo-module"],
+ cli-artifacts: ["mvn:org.apache.ignite:ignite-demo-module-cli"]
+ }
+}
\ No newline at end of file
diff --git a/modules/cli-demo/cli/src/test/resources/logback-test.xml b/modules/cli-demo/cli/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..6a1caa1
--- /dev/null
+++ b/modules/cli-demo/cli/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+<configuration>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <!-- encoders are assigned the type
+ ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <root level="error">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
\ No newline at end of file
diff --git a/modules/cli-demo/cli/src/test/resources/version.properties b/modules/cli-demo/cli/src/test/resources/version.properties
new file mode 100644
index 0000000..0d488d3
--- /dev/null
+++ b/modules/cli-demo/cli/src/test/resources/version.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+version=${project.version}