From 1d1266ab7487cf8551263be17385847905688637 Mon Sep 17 00:00:00 2001 From: hanbingleixue Date: Thu, 14 Sep 2023 21:07:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=A8=E6=80=81=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E5=8D=B8=E8=BD=BD=E7=9A=84=E5=91=BD=E4=BB=A4=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E6=89=A7=E8=A1=8C=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AgentUnInstallCommandExecutor.java | 32 ++++++++ .../sermant/core/command/Command.java | 47 +++++++++++ .../sermant/core/command/CommandExecutor.java | 33 ++++++++ .../core/command/CommandProcessor.java | 78 +++++++++++++++++++ .../PluginsInstallCommandExecutor.java | 46 +++++++++++ .../PluginsUnInstallCommandExecutor.java | 46 +++++++++++ .../core/command/CommandExecutorTest.java | 40 ++++++++++ .../sermant/premain/AgentLauncher.java | 27 ++++--- .../premain/common/BootArgsBuilderTest.java | 13 ++++ 9 files changed, 350 insertions(+), 12 deletions(-) create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/AgentUnInstallCommandExecutor.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/Command.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandExecutor.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandProcessor.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsInstallCommandExecutor.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsUnInstallCommandExecutor.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/test/java/com/huaweicloud/sermant/core/command/CommandExecutorTest.java diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/AgentUnInstallCommandExecutor.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/AgentUnInstallCommandExecutor.java new file mode 100644 index 0000000000..c648dc72b9 --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/AgentUnInstallCommandExecutor.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.core.command; + +import com.huaweicloud.sermant.core.AgentCoreEntrance; + +/** + * Agent卸载命令执行器 + * + * @author zhp + * @since 2023-09-09 + */ +public class AgentUnInstallCommandExecutor implements CommandExecutor { + @Override + public void execute(String args) { + AgentCoreEntrance.unInstall(); + } +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/Command.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/Command.java new file mode 100644 index 0000000000..0e6384a182 --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/Command.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.core.command; + +/** + * 动态安装卸载的指令枚举 + * + * @author zhp + * @since 2023-09-09 + */ +public enum Command { + /** + * 卸载agent指令 + */ + UNINSTALL_AGENT("UNINSTALL-AGENT"), + /** + * 安装插件指令 + */ + INSTALL_PLUGINS("INSTALL-PLUGINS"), + /** + * 卸载插件指令 + */ + UNINSTALL_PLUGINS("UNINSTALL-PLUGINS"); + private final String value; + + Command(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandExecutor.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandExecutor.java new file mode 100644 index 0000000000..5f39b1801c --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandExecutor.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.core.command; + +/** + * 指令执行器 + * + * @author zhp + * @since 2023-09-09 + */ +public interface CommandExecutor { + + /** + * 执行指令 + * + * @param args 指令参数 + */ + void execute(String args); +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandProcessor.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandProcessor.java new file mode 100644 index 0000000000..d685226a24 --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandProcessor.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.core.command; + +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.utils.StringUtils; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * 命令处理器 + * + * @author zhp + * @since 2023-09-09 + */ +public class CommandProcessor { + /** + * 命令执行器Map + */ + private static final Map COMMAND_EXECUTOR_MAP = new HashMap<>(); + + private static final Logger LOGGER = LoggerFactory.getLogger(); + + static { + COMMAND_EXECUTOR_MAP.put(Command.INSTALL_PLUGINS.getValue(), new PluginsInstallCommandExecutor()); + COMMAND_EXECUTOR_MAP.put(Command.UNINSTALL_AGENT.getValue(), new AgentUnInstallCommandExecutor()); + COMMAND_EXECUTOR_MAP.put(Command.UNINSTALL_PLUGINS.getValue(), new PluginsUnInstallCommandExecutor()); + } + + /** + * 构造函数 + */ + private CommandProcessor() { + } + + /** + * 处理指令 + * + * @param command 指令 + */ + public static void process(String command) { + if (StringUtils.isEmpty(command)) { + LOGGER.warning("Command information is empty."); + return; + } + LOGGER.log(Level.INFO, "Command information is {0}.", command); + String[] commandInfo = command.trim().split(":"); + if (commandInfo.length == 0) { + LOGGER.warning("Illegal command information."); + return; + } + CommandExecutor commandExecutor = COMMAND_EXECUTOR_MAP.get(commandInfo[0].toUpperCase(Locale.ROOT)); + if (commandExecutor == null) { + LOGGER.warning("No corresponding command executor found."); + return; + } + String commandArgs = commandInfo.length > 1 ? commandInfo[1] : null; + commandExecutor.execute(commandArgs); + } +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsInstallCommandExecutor.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsInstallCommandExecutor.java new file mode 100644 index 0000000000..291f116e64 --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsInstallCommandExecutor.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.core.command; + +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.plugin.PluginManager; +import com.huaweicloud.sermant.core.utils.StringUtils; + +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * 插件安装命令执行器 + * + * @author zhp + * @since 2023-09-09 + */ +public class PluginsInstallCommandExecutor implements CommandExecutor { + private static final Logger LOGGER = LoggerFactory.getLogger(); + + @Override + public void execute(String args) { + if (StringUtils.isEmpty(args)) { + LOGGER.log(Level.WARNING, "The argument of command[INSTALL-PLUGINS] is empty."); + return; + } + String[] pluginNames = args.split("\\|"); + PluginManager.install(Arrays.stream(pluginNames).collect(Collectors.toSet())); + } +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsUnInstallCommandExecutor.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsUnInstallCommandExecutor.java new file mode 100644 index 0000000000..1f325fb2ea --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsUnInstallCommandExecutor.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.core.command; + +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.plugin.PluginManager; +import com.huaweicloud.sermant.core.utils.StringUtils; + +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * 插件卸载命令执行器 + * + * @author zhp + * @since 2023-09-09 + */ +public class PluginsUnInstallCommandExecutor implements CommandExecutor { + private static final Logger LOGGER = LoggerFactory.getLogger(); + + @Override + public void execute(String args) { + if (StringUtils.isEmpty(args)) { + LOGGER.log(Level.WARNING, "The argument of command[UNINSTALL-PLUGINS] is empty."); + return; + } + String[] pluginNames = args.split("\\|"); + PluginManager.unInstall(Arrays.stream(pluginNames).collect(Collectors.toSet())); + } +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/test/java/com/huaweicloud/sermant/core/command/CommandExecutorTest.java b/sermant-agentcore/sermant-agentcore-core/src/test/java/com/huaweicloud/sermant/core/command/CommandExecutorTest.java new file mode 100644 index 0000000000..208f7e2393 --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/test/java/com/huaweicloud/sermant/core/command/CommandExecutorTest.java @@ -0,0 +1,40 @@ +package com.huaweicloud.sermant.core.command; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class CommandExecutorTest { + private CommandExecutor commandExecutor; + + @BeforeEach + public void setUp() { + commandExecutor = Mockito.mock(CommandExecutor.class); + } + + @AfterEach + public void tearDown() { + commandExecutor = null; + } + + @Test + public void testExecuteWhenArgsIsValidThenNoException() { + // Arrange + String validArgs = "validArgs"; + + // Act & Assert + assertDoesNotThrow(() -> commandExecutor.execute(validArgs)); + } + + @Test + public void testExecuteWhenArgsIsNullThenNoException() { + // Arrange + String nullArgs = null; + + // Act & Assert + assertDoesNotThrow(() -> commandExecutor.execute(nullArgs)); + } +} \ No newline at end of file diff --git a/sermant-agentcore/sermant-agentcore-premain/src/main/java/com/huaweicloud/sermant/premain/AgentLauncher.java b/sermant-agentcore/sermant-agentcore-premain/src/main/java/com/huaweicloud/sermant/premain/AgentLauncher.java index 3e3ffb0ecf..0d7d90c1fb 100644 --- a/sermant-agentcore/sermant-agentcore-premain/src/main/java/com/huaweicloud/sermant/premain/AgentLauncher.java +++ b/sermant-agentcore/sermant-agentcore-premain/src/main/java/com/huaweicloud/sermant/premain/AgentLauncher.java @@ -83,22 +83,25 @@ private static void launchAgent(String agentArgs, Instrumentation instrumentatio final Map argsMap = BootArgsBuilder.build(agentArgs); String artifact = (String) argsMap.get(BootConstant.ARTIFACT_NAME_KEY); - if (SermantManager.checkSermantStatus(artifact)) { - LOGGER.log(Level.WARNING, "Sermant for artifact is running,artifact is: " + artifact); - return; - } - // 添加核心库 LOGGER.info("Loading core library into SermantClassLoader."); SermantClassLoader sermantClassLoader = SermantManager.createSermant(artifact, loadCoreLibUrls()); + if (!SermantManager.checkSermantStatus(artifact)) { + // 当前artifact未安装,执行agent安装 + LOGGER.log(Level.INFO, "Loading sermant agent, artifact is: " + artifact); + sermantClassLoader.loadClass("com.huaweicloud.sermant.core.AgentCoreEntrance") + .getDeclaredMethod("install", String.class, Map.class, Instrumentation.class, boolean.class) + .invoke(null, artifact, argsMap, instrumentation, isDynamic); + LOGGER.log(Level.INFO, "Load sermant done, artifact is: " + artifact); + SermantManager.updateSermantStatus(artifact, true); + } else { + LOGGER.log(Level.INFO, "Sermant for artifact is running, artifact is: " + artifact); + } - // agent core入口 - LOGGER.log(Level.INFO, "Loading sermant agent, artifact is: " + artifact); - sermantClassLoader.loadClass("com.huaweicloud.sermant.core.AgentCoreEntrance") - .getDeclaredMethod("install", String.class, Map.class, Instrumentation.class, boolean.class) - .invoke(null, artifact, argsMap, instrumentation, isDynamic); - LOGGER.log(Level.INFO, "Load sermant done, artifact is: " + artifact); - SermantManager.updateSermantStatus(artifact, true); + // 处理启动参数中的指令 + sermantClassLoader.loadClass("com.huaweicloud.sermant.core.command.CommandProcessor") + .getDeclaredMethod("process", String.class) + .invoke(null, argsMap.get("command")); } catch (InvocationTargetException invocationTargetException) { LOGGER.log(Level.SEVERE, "Loading sermant agent failed: " + invocationTargetException.getTargetException().getMessage()); diff --git a/sermant-agentcore/sermant-agentcore-premain/src/test/java/com/huaweicloud/sermant/premain/common/BootArgsBuilderTest.java b/sermant-agentcore/sermant-agentcore-premain/src/test/java/com/huaweicloud/sermant/premain/common/BootArgsBuilderTest.java index 696ee70a15..8e1c9975f7 100644 --- a/sermant-agentcore/sermant-agentcore-premain/src/test/java/com/huaweicloud/sermant/premain/common/BootArgsBuilderTest.java +++ b/sermant-agentcore/sermant-agentcore-premain/src/test/java/com/huaweicloud/sermant/premain/common/BootArgsBuilderTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -105,4 +106,16 @@ private static void setEnv(Map envMap) throws NoSuchFieldException, IllegalAcces } } } + + /** + * 测试参数解析 + */ + @Test + public void testParseArgs(){ + String agentArgs = "appName=test,command=INSTALL_PLUGIN:monitor|flowcontrol,server.port=9000"; + Map argsMap = BootArgsBuilder.build(agentArgs); + Assert.assertEquals("test", argsMap.get("appName")); + Assert.assertEquals("9000", argsMap.get("server.port")); + Assert.assertEquals("INSTALL_PLUGIN:monitor|flowcontrol", argsMap.get("command")); + } } \ No newline at end of file