Skip to content

Commit

Permalink
增加动态安装卸载的命令解析执行器
Browse files Browse the repository at this point in the history
  • Loading branch information
hanbingleixue committed Sep 14, 2023
1 parent 1823cec commit 1d1266a
Show file tree
Hide file tree
Showing 9 changed files with 350 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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<String, CommandExecutor> 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);
}
}
Original file line number Diff line number Diff line change
@@ -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()));
}
}
Original file line number Diff line number Diff line change
@@ -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()));
}
}
Original file line number Diff line number Diff line change
@@ -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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,22 +83,25 @@ private static void launchAgent(String agentArgs, Instrumentation instrumentatio
final Map<String, Object> 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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<String, Object> 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"));
}
}

0 comments on commit 1d1266a

Please sign in to comment.