This is an automated email from the ASF dual-hosted git repository.

ptupitsyn 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 cf96fb5328 IGNITE-17754 Print REST API endpoint address on node start 
(#1274)
cf96fb5328 is described below

commit cf96fb5328c4ff6c56f11a63e6103af25702c29b
Author: Aleksandr <[email protected]>
AuthorDate: Fri Nov 25 22:57:47 2022 +0800

    IGNITE-17754 Print REST API endpoint address on node start (#1274)
    
    * Write endpoint address to file on startup.
    * Read address from file in the start script and print to stdout.
---
 .../apache/ignite/internal/rest/RestComponent.java |   8 +-
 .../component/ItRestAddressReportTest.java         | 100 ++++++++++++++++++++
 .../ignite-config-rest-port-not-default.json       |  15 +++
 .../org/apache/ignite/internal/app/IgniteImpl.java |  10 ++
 .../internal/component/RestAddressReporter.java    |  60 ++++++++++++
 .../component/RestAddressReporterTest.java         | 103 +++++++++++++++++++++
 packaging/build.gradle                             |   2 +-
 packaging/zip/ignite3db                            |  16 +++-
 8 files changed, 308 insertions(+), 6 deletions(-)

diff --git 
a/modules/rest/src/main/java/org/apache/ignite/internal/rest/RestComponent.java 
b/modules/rest/src/main/java/org/apache/ignite/internal/rest/RestComponent.java
index 53c2991246..4ae58eeb3d 100644
--- 
a/modules/rest/src/main/java/org/apache/ignite/internal/rest/RestComponent.java
+++ 
b/modules/rest/src/main/java/org/apache/ignite/internal/rest/RestComponent.java
@@ -27,6 +27,8 @@ import io.swagger.v3.oas.annotations.info.Contact;
 import io.swagger.v3.oas.annotations.info.Info;
 import io.swagger.v3.oas.annotations.info.License;
 import java.net.BindException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.List;
 import java.util.Map;
 import org.apache.ignite.internal.logger.IgniteLogger;
@@ -192,6 +194,10 @@ public class RestComponent implements IgniteComponent {
             throw new IgniteInternalException("RestComponent has not been 
started");
         }
 
-        return LOCALHOST;
+        try {
+            return InetAddress.getLocalHost().getHostAddress();
+        } catch (UnknownHostException e) {
+            return LOCALHOST;
+        }
     }
 }
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/component/ItRestAddressReportTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/component/ItRestAddressReportTest.java
new file mode 100644
index 0000000000..6e31bbe4ec
--- /dev/null
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/component/ItRestAddressReportTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.internal.component;
+
+import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+
+import java.io.File;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgnitionManager;
+import org.apache.ignite.app.IgniteRunner;
+import org.apache.ignite.internal.runner.app.IgniteRunnerTest;
+import org.apache.ignite.internal.testframework.WorkDirectory;
+import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+/**
+ * Test that after Ignite is started there is a file with REST server address 
in working directory.
+ */
+@ExtendWith(WorkDirectoryExtension.class)
+public class ItRestAddressReportTest {
+    private static final String NODE_NAME = "node";
+
+    @WorkDirectory
+    private Path workDir;
+
+    private static int cutPort(String retAddress) {
+        return Integer.parseInt(retAddress.split(":")[1]);
+    }
+
+    @Test
+    @DisplayName("Should report rest port to the file after RestComponent 
started")
+    void restPortReportedToFile() throws Exception {
+        // Given configuration with rest port configured rest.port=10333, 
rest.portRange=10
+        Path configPath = 
Path.of(IgniteRunnerTest.class.getResource("/ignite-config-rest-port-not-default.json").toURI());
+
+        // When start node
+        CompletableFuture<Ignite> ign = IgniteRunner.start(
+                "--config-path", configPath.toAbsolutePath().toString(),
+                "--work-dir", 
workDir.resolve(NODE_NAME).toAbsolutePath().toString(),
+                "--node-name", NODE_NAME
+        );
+        // And init cluster
+        IgnitionManager.init(NODE_NAME, List.of(NODE_NAME), "cluster");
+
+        // Then node is started
+        assertThat(ign, willCompleteSuccessfully());
+
+        // And there is a file in work dir with the rest address
+        File reportFile = 
workDir.resolve(NODE_NAME).resolve("rest-address").toFile();
+        assertThat(reportFile.exists(), is(true));
+
+        // And the file contains valid rest server network address
+        URI restUri = 
URI.create(Files.readString(workDir.resolve(NODE_NAME).resolve("rest-address")));
+        assertThat(restUri.getHost(), is(equalTo(getHostAddress())));
+        // And port is in configured range
+        int port = restUri.getPort();
+        assertThat(port >= 10333 && port < 10333 + 10, is(true));
+
+        // When stop node
+        IgnitionManager.stop(NODE_NAME);
+
+        // Then the file is removed
+        assertThat(reportFile.exists(), is(false));
+    }
+
+    private static String getHostAddress() {
+        try {
+            return InetAddress.getLocalHost().getHostAddress();
+        } catch (UnknownHostException e) {
+            return "localhost";
+        }
+    }
+}
diff --git 
a/modules/runner/src/integrationTest/resources/ignite-config-rest-port-not-default.json
 
b/modules/runner/src/integrationTest/resources/ignite-config-rest-port-not-default.json
new file mode 100644
index 0000000000..bd4c4666f7
--- /dev/null
+++ 
b/modules/runner/src/integrationTest/resources/ignite-config-rest-port-not-default.json
@@ -0,0 +1,15 @@
+{
+    "network": {
+        "port": 3344,
+        "portRange": 10,
+        "nodeFinder": {
+            "netClusterNodes": [
+                "localhost:3344"
+            ]
+        }
+    },
+    "rest": {
+        "port": 10333,
+        "portRange": 10
+    }
+}
diff --git 
a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java 
b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
index 8f6586f14b..bee5d6a461 100644
--- 
a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
+++ 
b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
@@ -18,6 +18,8 @@
 package org.apache.ignite.internal.app;
 
 import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -40,6 +42,7 @@ import 
org.apache.ignite.internal.cluster.management.raft.ClusterStateStorage;
 import 
org.apache.ignite.internal.cluster.management.raft.RocksDbClusterStateStorage;
 import 
org.apache.ignite.internal.cluster.management.rest.ClusterManagementRestFactory;
 import 
org.apache.ignite.internal.cluster.management.topology.LogicalTopologyImpl;
+import org.apache.ignite.internal.component.RestAddressReporter;
 import org.apache.ignite.internal.components.LongJvmPauseDetector;
 import org.apache.ignite.internal.compute.ComputeComponent;
 import org.apache.ignite.internal.compute.ComputeComponentImpl;
@@ -235,6 +238,8 @@ public class IgniteImpl implements Ignite {
 
     private final OutgoingSnapshotsManager outgoingSnapshotsManager;
 
+    private final RestAddressReporter restAddressReporter;
+
     /**
      * The Constructor.
      *
@@ -347,6 +352,8 @@ public class IgniteImpl implements Ignite {
 
         restComponent = createRestComponent(name);
 
+        restAddressReporter = new RestAddressReporter(workDir);
+
         baselineMgr = new BaselineManager(
                 clusterCfgMgr,
                 metaStorageMgr,
@@ -522,6 +529,8 @@ public class IgniteImpl implements Ignite {
 
             clusterSvc.updateMetadata(new NodeMetadata(restComponent.host(), 
restComponent.port()));
 
+            restAddressReporter.writeReport(restAddress());
+
             LOG.info("Components started, joining the cluster");
 
             return cmgMgr.joinFuture()
@@ -614,6 +623,7 @@ public class IgniteImpl implements Ignite {
      */
     public void stop() {
         lifecycleManager.stopNode();
+        restAddressReporter.removeReport();
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/runner/src/main/java/org/apache/ignite/internal/component/RestAddressReporter.java
 
b/modules/runner/src/main/java/org/apache/ignite/internal/component/RestAddressReporter.java
new file mode 100644
index 0000000000..9d389a230d
--- /dev/null
+++ 
b/modules/runner/src/main/java/org/apache/ignite/internal/component/RestAddressReporter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.internal.component;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.apache.ignite.lang.ErrorGroups.Common;
+import org.apache.ignite.lang.IgniteException;
+import org.apache.ignite.network.NetworkAddress;
+
+/**
+ * Can write network address to file that could be used by other systems to 
know on what port Ignite 3 REST server is started.
+ */
+public class RestAddressReporter {
+
+    private static final String REPORT_FILE_NAME = "rest-address";
+
+    private final Path workDir;
+
+    /** Main constructor that accept the root directory where report file will 
be written. */
+    public RestAddressReporter(Path workDir) {
+        this.workDir = workDir;
+    }
+
+    /** Write network address to file. */
+    public void writeReport(NetworkAddress networkAddress) {
+        try {
+            Files.writeString(workDir.resolve(REPORT_FILE_NAME), "http://"; + 
networkAddress.host() + ":" + networkAddress.port());
+        } catch (IOException e) {
+            String message = "Unexpected error when trying to write REST 
server network address to file";
+            throw new IgniteException(Common.UNEXPECTED_ERR, message, e);
+        }
+    }
+
+    /** Remove report file. The method is expected to be called on node stop. 
*/
+    public void removeReport() {
+        try {
+            Files.delete(workDir.resolve(REPORT_FILE_NAME));
+        } catch (IOException e) {
+            String message = "Unexpected error when trying to remove REST 
server network address file";
+            throw new IgniteException(Common.UNEXPECTED_ERR, message, e);
+        }
+    }
+}
diff --git 
a/modules/runner/src/test/java/org/apache/ignite/internal/component/RestAddressReporterTest.java
 
b/modules/runner/src/test/java/org/apache/ignite/internal/component/RestAddressReporterTest.java
new file mode 100644
index 0000000000..654e325863
--- /dev/null
+++ 
b/modules/runner/src/test/java/org/apache/ignite/internal/component/RestAddressReporterTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.internal.component;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.apache.ignite.lang.ErrorGroups.Common;
+import org.apache.ignite.lang.IgniteException;
+import org.apache.ignite.network.NetworkAddress;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+/** Test for {@link RestAddressReporter}. */
+class RestAddressReporterTest {
+
+    private static final String REST_ADDRESS_FILENAME = "rest-address";
+
+    @Test
+    @DisplayName("REST server network address is reported to file")
+    void networkAddressReported(@TempDir Path tmpDir) throws IOException {
+        // Given
+        RestAddressReporter reporter = new RestAddressReporter(tmpDir);
+
+        // When
+        reporter.writeReport(new NetworkAddress("localhost", 9999));
+
+        // Then there is a report
+        String restAddress = 
Files.readString(tmpDir.resolve(REST_ADDRESS_FILENAME));
+        assertThat(restAddress, equalTo("http://localhost:9999";));
+    }
+
+    @Test
+    @DisplayName("File with network address is removed")
+    void reportDeleted(@TempDir Path tmpDir) throws IOException {
+        // Given reported address
+        RestAddressReporter reporter = new RestAddressReporter(tmpDir);
+        reporter.writeReport(new NetworkAddress("localhost", 9999));
+        // And file exists
+        assertThat(Files.exists(tmpDir.resolve(REST_ADDRESS_FILENAME)), 
is(true));
+
+        // When
+        reporter.removeReport();
+
+        // Then file is removed
+        assertThat(Files.exists(tmpDir.resolve(REST_ADDRESS_FILENAME)), 
is(false));
+    }
+
+    @Test
+    @DisplayName("If there is no report file for some reason then throw an 
exception")
+    void throwsExceptionWhenThereIsNoFile(@TempDir Path tmpDir) {
+        // Given
+        Path path = Path.of(tmpDir.toUri() + "/nosuchpath");
+        RestAddressReporter reporter = new RestAddressReporter(path);
+
+        // When try to removeReport
+        IgniteException thrown = assertThrows(IgniteException.class, 
reporter::removeReport);
+
+        // Then exception thrown with proper message
+        assertThat(thrown.getMessage(), containsString("Unexpected error when 
trying to remove REST server network address file"));
+        // And it has COMMON error group
+        assertThat(thrown.groupName(), 
equalTo(Common.COMMON_ERR_GROUP.name()));
+    }
+
+    @Test
+    @DisplayName("If there is a file with report then it should be rewritten")
+    void rewritesAlreadyExistingFile(@TempDir Path tmpDir) throws IOException {
+        // Given reported address to file
+        Files.writeString(
+                tmpDir.resolve(REST_ADDRESS_FILENAME),
+                new NetworkAddress("localhost", 9999).toString()
+        );
+
+        // When try to write it again but with another port
+        new RestAddressReporter(tmpDir).writeReport(new 
NetworkAddress("localhost", 4444));
+
+        // Then file rewritten
+        String restAddress = 
Files.readString(tmpDir.resolve(REST_ADDRESS_FILENAME));
+        assertThat(restAddress, equalTo("http://localhost:4444";));
+    }
+}
diff --git a/packaging/build.gradle b/packaging/build.gradle
index 5c013bcf9b..1aa3bfb03e 100644
--- a/packaging/build.gradle
+++ b/packaging/build.gradle
@@ -137,4 +137,4 @@ task buildAndSignAllSrcZip(type: Sign) {
 
 signing {
     sign allDistZip
-}
\ No newline at end of file
+}
diff --git a/packaging/zip/ignite3db b/packaging/zip/ignite3db
index 9e90f2fdd2..898af35d36 100755
--- a/packaging/zip/ignite3db
+++ b/packaging/zip/ignite3db
@@ -17,11 +17,10 @@
 # limitations under the License.
 #
 
-SCRIPT=$(readlink -f "$0")
-SCRIPT_DIR=$(dirname "$SCRIPT")
+SCRIPT_DIR=$(dirname "$0")
 
-cd ${SCRIPT_DIR} || exit
-cd .. # SCRIPT_DIR points at bin
+cd ${SCRIPT_DIR} || exit  # SCRIPT_DIR points at bin
+cd .. # now SCRIPT_DIR points at parent dir for bin
 
 # if IGNITE_HOME is not set than it will be parent directory for bin
 if [ -z ${IGNITE_HOME+x} ]; then IGNITE_HOME=$(pwd); fi
@@ -33,12 +32,21 @@ if [ -z ${IGNITE_HOME+x} ]; then IGNITE_HOME=$(pwd); fi
 cd ${IGNITE_HOME} || exit
 
 start() {
+  echo "Starting Ignite 3..."
+
   CMD="${JAVA_CMD_WITH_ARGS} ${APPLICATION_ARGS}"
   $CMD >>/dev/null 2>&1 </dev/null & echo $! >${IGNITE_HOME}/pid
+
+  rest_address_file=${WORK_DIR}/rest-address
+  while [ ! -f "$rest_address_file" ]; do sleep 0.5; done
+    rest_address=$(cat "$rest_address_file")
+
+  echo "Node named ${NODE_NAME} started successfully. REST address is 
$rest_address"
 }
 
 stop() {
   kill -9 "$(cat ${IGNITE_HOME}/pid)"
+  rm ${WORK_DIR}/rest-address
 }
 
 case $1 in

Reply via email to