From b6799e2e7982c065bd1c0501e49b53db6aac395a Mon Sep 17 00:00:00 2001 From: Natalia Pozhidaeva Date: Mon, 12 Feb 2024 19:42:15 -0500 Subject: [PATCH] [#1876] RegisterShell saves to PfSHell resolved IP address --- .../com/rultor/agents/shells/PfShell.java | 4 +- .../rultor/agents/shells/RegistersShell.java | 20 +++-- .../com/rultor/agents/shells/SmartHost.java | 77 +++++++++++++++++++ .../agents/shells/RegistersShellTest.java | 38 ++++++++- 4 files changed, 125 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/rultor/agents/shells/SmartHost.java diff --git a/src/main/java/com/rultor/agents/shells/PfShell.java b/src/main/java/com/rultor/agents/shells/PfShell.java index 5a1cfb1593..a0f80f18bf 100644 --- a/src/main/java/com/rultor/agents/shells/PfShell.java +++ b/src/main/java/com/rultor/agents/shells/PfShell.java @@ -54,7 +54,7 @@ public final class PfShell { private final transient Profile profile; /** - * Host name. + * Host name or IP address. */ private final transient String addr; @@ -76,7 +76,7 @@ public final class PfShell { /** * Constructor. * @param prof Profile - * @param host Default IP address + * @param host Default IP address or Host name * @param port Default Port of server * @param login Default Login * @param key Default Private SSH key diff --git a/src/main/java/com/rultor/agents/shells/RegistersShell.java b/src/main/java/com/rultor/agents/shells/RegistersShell.java index 4ed329d4cf..0ee0b32899 100644 --- a/src/main/java/com/rultor/agents/shells/RegistersShell.java +++ b/src/main/java/com/rultor/agents/shells/RegistersShell.java @@ -35,6 +35,7 @@ import com.rultor.agents.AbstractAgent; import com.rultor.spi.Profile; import java.io.IOException; +import java.net.UnknownHostException; import lombok.EqualsAndHashCode; import lombok.ToString; import org.xembly.Directive; @@ -59,20 +60,17 @@ public final class RegistersShell extends AbstractAgent { /** * Constructor. * @param profile Profile - * @param host Default IP address + * @param host Default IP address or host name * @param port Default Port of server * @param user Default Login * @param key Default Private SSH key + * @throws UnknownHostException in case of host is not resolved * @checkstyle ParameterNumberCheck (6 lines) */ public RegistersShell(final Profile profile, final String host, - final int port, final String user, final String key) { + final int port, final String user, final String key) + throws UnknownHostException { super("/talk[daemon and not(shell)]"); - if (host.isEmpty()) { - throw new IllegalArgumentException( - "Host is mandatory" - ); - } if (user.isEmpty()) { throw new IllegalArgumentException( "User name is mandatory" @@ -83,7 +81,13 @@ public RegistersShell(final Profile profile, final String host, "SSH key is mandatory" ); } - this.shell = new PfShell(profile, host, port, user, key); + this.shell = new PfShell( + profile, + new SmartHost(host).ip(), + port, + user, + key + ); } @Override diff --git a/src/main/java/com/rultor/agents/shells/SmartHost.java b/src/main/java/com/rultor/agents/shells/SmartHost.java new file mode 100644 index 0000000000..00d3014d1e --- /dev/null +++ b/src/main/java/com/rultor/agents/shells/SmartHost.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2009-2024 Yegor Bugayenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: 1) Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. 2) Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. 3) Neither the name of the rultor.com nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.rultor.agents.shells; + +import com.jcabi.aspects.Immutable; +import java.net.InetAddress; +import java.net.UnknownHostException; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * Host. + * + * @since 1.77.0 + */ +@Immutable +@ToString +@EqualsAndHashCode(of = { "host" }) +@SuppressWarnings({"PMD.ShortMethodName", + "PMD.ConstructorOnlyInitializesOrCallOtherConstructors"}) +final class SmartHost { + /** + * Server address. + */ + private final transient InetAddress host; + + /** + * Ctor. + * @param address Host name or IP address + * @throws UnknownHostException in case of address is not resolved + */ + SmartHost(final String address) throws UnknownHostException { + if (address.isEmpty()) { + throw new IllegalArgumentException( + "Host is mandatory" + ); + } + this.host = InetAddress.getByName(address); + } + + /** + * Host's IP. + * + * @return Ip address + * @checkstyle MethodNameCheck (3 lines) + */ + public String ip() { + return this.host.getHostAddress(); + } +} diff --git a/src/test/java/com/rultor/agents/shells/RegistersShellTest.java b/src/test/java/com/rultor/agents/shells/RegistersShellTest.java index 19a2e6b14b..4e9aba5077 100644 --- a/src/test/java/com/rultor/agents/shells/RegistersShellTest.java +++ b/src/test/java/com/rultor/agents/shells/RegistersShellTest.java @@ -46,10 +46,11 @@ * * @since 1.0 */ +@SuppressWarnings("PMD.AvoidUsingHardCodedIP") final class RegistersShellTest { /** - * RegistersShell can register a shell. + * RegistersShell can register a shell with hostname. * @throws Exception In case of error. */ @Test @@ -72,7 +73,7 @@ void registersShell() throws Exception { ).asString() ) ), - "localhost", 22, "rultor", "def-key" + "127.0.0.1", 22, "rultor", "def-key" ); final Talk talk = new Talk.InFile(); talk.modify( @@ -93,6 +94,36 @@ void registersShell() throws Exception { ); } + /** + * RegistersShell can register shell by IP. + * @throws Exception In case of error. + */ + @Test + void registerShellWithIP() { + final String host = "192.168.5.49"; + final int port = 221; + final String key = ""; + final String login = "john"; + Assertions.assertDoesNotThrow( + () -> new RegistersShell( + new Profile.Fixed( + new XMLDocument( + new Joined( + " ", + "

", + String.format("%s", host), + String.format("%d", port), + String.format("%s", key), + String.format("%s", login), + "

" + ).asString() + ) + ), + host, 22, "rultor", "def-key" + ) + ); + } + /** * RegistersShell can handle broken profile. * @throws Exception In case of error. @@ -102,12 +133,11 @@ void handlesBrokenProfileGracefully() throws Exception { final Profile profile = Mockito.mock(Profile.class); Mockito.doThrow(new Profile.ConfigException("")).when(profile).read(); final Agent agent = new RegistersShell( - profile, "test-host", 1, "test-user", "test-key" + profile, "localhost", 1, "test-user", "test-key" ); final Talk talk = new Talk.InFile(); Assertions.assertDoesNotThrow( () -> agent.execute(talk) ); } - }