Merge branch 'local-dev'

# Conflicts:
#	agent-go/octopus-agent-dev.yaml
This commit is contained in:
zeaslity
2023-06-28 16:33:30 +08:00
160 changed files with 7280 additions and 2874 deletions

View File

@@ -0,0 +1,9 @@
{
"description": "",
"directory": "~.fastRequest~collections~Root~Default Group",
"filePath": "~.fastRequest~collections~Root~Default Group~",
"groupId": "1",
"id": "1",
"name": "Default Group",
"type": 1
}

View File

@@ -0,0 +1,9 @@
{
"description": "",
"directory": "~.fastRequest~collections~Root",
"filePath": "~.fastRequest~collections~Root~",
"groupId": "-1",
"id": "0",
"name": "Root",
"type": 1
}

View File

@@ -0,0 +1,8 @@
{
"description": "",
"directory": "~.fastRequest~collections~Root~server~ExecutionController",
"filePath": "~.fastRequest~collections~Root~server~ExecutionController~",
"id": "20230222093108443",
"name": "ExecutionController",
"type": 3
}

View File

@@ -0,0 +1,37 @@
{
"activeGroup": "Default",
"apiParamGroup": {},
"childList": [],
"description": "",
"directory": "~.fastRequest~collections~Root~server~ExecutionController",
"domain": "http://localhost:9999",
"enableEnv": "local",
"enableProject": "ProjectOctopus",
"filePath": "~.fastRequest~collections~Root~server~ExecutionController~patchCommandToAgentAll.rapi",
"headerList": [],
"id": "api_io.wdd.rpc.controller.ExecutionController.patchCommandToAgentAll",
"name": "[命令]- 发送命令至所有的主机",
"paramGroup": {
"bodyKeyValueListJson": "",
"className": "io.wdd.rpc.controller.ExecutionController",
"jsonDocument": "",
"method": "patchCommandToAgentAll",
"methodDescription": "[命令]- 发送命令至所有的主机",
"methodType": "POST",
"multipartKeyValueListJson": "[]",
"originUrl": "/octopus/server/executor/command/all",
"pathParamsKeyValueListJson": "[]",
"postScript": "",
"postType": "json",
"preScript": "",
"returnDocument": "{\n\t\"code\":\"No comment,Type =Number\",\n\t\"msg\":\"No comment,Type =String\",\n\t\"data\":{}\n}",
"tempId": "",
"url": "/octopus/server/executor/command/all",
"urlEncodedKeyValueListJson": "[{\"comment\":\"命令行\",\"customFlag\":2,\"enabled\":true,\"key\":\"commandList\",\"type\":\"String\",\"value\":\"apt-get,update\"},{\"comment\":\"\",\"customFlag\":2,\"enabled\":true,\"key\":\"type\",\"type\":\"String\",\"value\":\"\"}]",
"urlEncodedKeyValueListText": "commandList=apt-get,update\n&type=",
"urlParamsKeyValueListJson": "[]",
"urlParamsKeyValueListText": ""
},
"tempId": "id_io.wdd.rpc.controller.ExecutionController.patchCommandToAgentAll",
"type": 2
}

View File

@@ -0,0 +1,37 @@
{
"activeGroup": "Default",
"apiParamGroup": {},
"childList": [],
"description": "",
"directory": "~.fastRequest~collections~Root~server~SchedulerController",
"domain": "http://localhost:9999",
"enableEnv": "local",
"enableProject": "ProjectOctopus",
"filePath": "~.fastRequest~collections~Root~server~SchedulerController~createScriptScheduler.rapi",
"headerList": [],
"id": "api_io.wdd.rpc.controller.SchedulerController.createScriptScheduler",
"name": "新增一个定时脚本任务",
"paramGroup": {
"bodyKeyValueListJson": "{\n \"schedulerUuid\": \"\",\n \"name\": \"测试任务\",\n \"cronExpress\": \"30 */30 * * * ? *\",\n \"description\": \"这是注释内容\",\n \"scriptContent\": \"echo yes \\napt-get update \\necho no \\napt-get install nginx -y\",\n \"targetMachine\": \"Chengdu-amd64-98-98066f\",\n \"lastExecutionId\": null,\n \"lastExecutionResultKey\": \"\",\n \"lastExecutionStatus\": null ,\n \"createTime\": \"\",\n \"updateTime\": \"\",\n \"nextScheduleTime\": \"\",\n \"lastScheduleTime\": \"\"\n}",
"className": "io.wdd.rpc.controller.SchedulerController",
"jsonDocument": "{\n \"schedulerUuid\": \"No comment,Value =schedulerUuid_9dr3w\",\n \"name\": \"No comment,Value =name_ucmeh\",\n \"cronExpress\": \"No comment,Value =cronExpress_qbwqm\",\n \"description\": \"No comment,Value =description_drj0c\",\n \"scriptContent\": \"脚本任务的内容\",\n \"targetMachine\": \"执行目标机器agent_topic_name列表使用, 分隔\",\n \"lastExecutionId\": \"与 execution_log表的主键对应,方便查询执行日志\",\n \"lastExecutionResultKey\": \"与 execution_log表的 result_key 对应,方便查询执行日志\",\n \"lastExecutionStatus\": \"任务上次执行状态\",\n \"createTime\": \"定时脚本任务创建时间\",\n \"updateTime\": \"上次更新时间\",\n \"nextScheduleTime\": \"任务下次计划执行时间\",\n \"lastScheduleTime\": \"任务上次计划执行时间\"\n}",
"method": "createScriptScheduler",
"methodDescription": "新增一个定时脚本任务",
"methodType": "POST",
"multipartKeyValueListJson": "[]",
"originUrl": "/octopus/server/scheduler/script/create",
"pathParamsKeyValueListJson": "[]",
"postScript": "",
"postType": "json",
"preScript": "",
"returnDocument": "{\n\t\"code\":\"No comment,Type =Number\",\n\t\"msg\":\"No comment,Type =String\",\n\t\"data\":{}\n}",
"tempId": "",
"url": "/octopus/server/scheduler/script/create",
"urlEncodedKeyValueListJson": "[]",
"urlEncodedKeyValueListText": "",
"urlParamsKeyValueListJson": "[]",
"urlParamsKeyValueListText": ""
},
"tempId": "id_io.wdd.rpc.controller.SchedulerController.createScriptScheduler",
"type": 2
}

View File

@@ -0,0 +1,8 @@
{
"description": "",
"directory": "~.fastRequest~collections~Root~server~SchedulerController",
"filePath": "~.fastRequest~collections~Root~server~SchedulerController~",
"id": "20230116173428298",
"name": "SchedulerController",
"type": 3
}

View File

@@ -0,0 +1,37 @@
{
"activeGroup": "Default",
"apiParamGroup": {},
"childList": [],
"description": "",
"directory": "~.fastRequest~collections~Root~server~SchedulerController",
"domain": "http://localhost:9999",
"enableEnv": "local",
"enableProject": "ProjectOctopus",
"filePath": "~.fastRequest~collections~Root~server~SchedulerController~queryAllQuartzJob.rapi",
"headerList": [],
"id": "api_io.wdd.rpc.controller.SchedulerController.queryAllQuartzJob",
"name": "查询所有job",
"paramGroup": {
"bodyKeyValueListJson": "",
"className": "io.wdd.rpc.controller.SchedulerController",
"jsonDocument": "",
"method": "queryAllQuartzJob",
"methodDescription": "查询所有job",
"methodType": "GET",
"multipartKeyValueListJson": "[]",
"originUrl": "/octopus/server/scheduler/queryAllJob",
"pathParamsKeyValueListJson": "[]",
"postScript": "",
"postType": "json",
"preScript": "",
"returnDocument": "{\n\t\"code\":\"No comment,Type =Number\",\n\t\"msg\":\"No comment,Type =String\",\n\t\"data\":{}\n}",
"tempId": "",
"url": "/octopus/server/scheduler/queryAllJob",
"urlEncodedKeyValueListJson": "[]",
"urlEncodedKeyValueListText": "",
"urlParamsKeyValueListJson": "[]",
"urlParamsKeyValueListText": ""
},
"tempId": "id_io.wdd.rpc.controller.SchedulerController.queryAllQuartzJob",
"type": 2
}

View File

@@ -0,0 +1,37 @@
{
"activeGroup": "Default",
"apiParamGroup": {},
"childList": [],
"description": "",
"directory": "~.fastRequest~collections~Root~server~SchedulerController",
"domain": "http://localhost:9999",
"enableEnv": "local",
"enableProject": "ProjectOctopus",
"filePath": "~.fastRequest~collections~Root~server~SchedulerController~queryAllTriggers.rapi",
"headerList": [],
"id": "api_io.wdd.rpc.controller.SchedulerController.queryAllTriggers",
"name": "查询所有的触发器Trigger",
"paramGroup": {
"bodyKeyValueListJson": "",
"className": "io.wdd.rpc.controller.SchedulerController",
"jsonDocument": "",
"method": "queryAllTriggers",
"methodDescription": "查询所有的触发器Trigger",
"methodType": "GET",
"multipartKeyValueListJson": "[]",
"originUrl": "/octopus/server/scheduler/allTriggers",
"pathParamsKeyValueListJson": "[]",
"postScript": "",
"postType": "json",
"preScript": "",
"returnDocument": "{\n\t\"code\":\"No comment,Type =Number\",\n\t\"msg\":\"No comment,Type =String\",\n\t\"data\":{}\n}",
"tempId": "",
"url": "/octopus/server/scheduler/allTriggers",
"urlEncodedKeyValueListJson": "[]",
"urlEncodedKeyValueListText": "",
"urlParamsKeyValueListJson": "[]",
"urlParamsKeyValueListText": ""
},
"tempId": "id_io.wdd.rpc.controller.SchedulerController.queryAllTriggers",
"type": 2
}

View File

@@ -0,0 +1,37 @@
{
"activeGroup": "Default",
"apiParamGroup": {},
"childList": [],
"description": "",
"directory": "~.fastRequest~collections~Root~server~SchedulerController",
"domain": "http://localhost:9999",
"enableEnv": "local",
"enableProject": "ProjectOctopus",
"filePath": "~.fastRequest~collections~Root~server~SchedulerController~queryRunQuartzJob.rapi",
"headerList": [],
"id": "api_io.wdd.rpc.controller.SchedulerController.queryRunQuartzJob",
"name": "查询所有运行job",
"paramGroup": {
"bodyKeyValueListJson": "",
"className": "io.wdd.rpc.controller.SchedulerController",
"jsonDocument": "",
"method": "queryRunQuartzJob",
"methodDescription": "查询所有运行job",
"methodType": "POST",
"multipartKeyValueListJson": "[]",
"originUrl": "/octopus/server/scheduler/queryRunJob",
"pathParamsKeyValueListJson": "[]",
"postScript": "",
"postType": "json",
"preScript": "",
"returnDocument": "{\n\t\"code\":\"No comment,Type =Number\",\n\t\"msg\":\"No comment,Type =String\",\n\t\"data\":{}\n}",
"tempId": "",
"url": "/octopus/server/scheduler/queryRunJob",
"urlEncodedKeyValueListJson": "[]",
"urlEncodedKeyValueListText": "",
"urlParamsKeyValueListJson": "[]",
"urlParamsKeyValueListText": ""
},
"tempId": "id_io.wdd.rpc.controller.SchedulerController.queryRunQuartzJob",
"type": 2
}

View File

@@ -0,0 +1,37 @@
{
"activeGroup": "Default",
"apiParamGroup": {},
"childList": [],
"description": "",
"directory": "~.fastRequest~collections~Root~server~StatusController",
"domain": "http://localhost:9999",
"enableEnv": "local",
"enableProject": "ProjectOctopus",
"filePath": "~.fastRequest~collections~Root~server~StatusController~GetHealthyStatusAgentList.rapi",
"headerList": [],
"id": "api_io.wdd.rpc.controller.StatusController.GetHealthyStatusAgentList",
"name": "[ 状态-Agent ] Map",
"paramGroup": {
"bodyKeyValueListJson": "",
"className": "io.wdd.rpc.controller.StatusController",
"jsonDocument": "",
"method": "GetHealthyStatusAgentList",
"methodDescription": "[ 状态-Agent ] Map",
"methodType": "GET",
"multipartKeyValueListJson": "[]",
"originUrl": "/octopus/server/status/status/agent",
"pathParamsKeyValueListJson": "[]",
"postScript": "",
"postType": "json",
"preScript": "",
"returnDocument": "{\n\t\"code\":\"No comment,Type =Number\",\n\t\"msg\":\"No comment,Type =String\",\n\t\"data\":{}\n}",
"tempId": "",
"url": "/octopus/server/status/status/agent",
"urlEncodedKeyValueListJson": "[]",
"urlEncodedKeyValueListText": "",
"urlParamsKeyValueListJson": "[]",
"urlParamsKeyValueListText": ""
},
"tempId": "id_io.wdd.rpc.controller.StatusController.GetHealthyStatusAgentList",
"type": 2
}

View File

@@ -0,0 +1,37 @@
{
"activeGroup": "Default",
"apiParamGroup": {},
"childList": [],
"description": "",
"directory": "~.fastRequest~collections~Root~server~StatusController",
"domain": "http://localhost:9999",
"enableEnv": "local",
"enableProject": "ProjectOctopus",
"filePath": "~.fastRequest~collections~Root~server~StatusController~ManualUpdateAgentStatus.rapi",
"headerList": [],
"id": "api_io.wdd.rpc.controller.StatusController.ManualUpdateAgentStatus",
"name": "手动更新Agent的状态",
"paramGroup": {
"bodyKeyValueListJson": "",
"className": "io.wdd.rpc.controller.StatusController",
"jsonDocument": "",
"method": "ManualUpdateAgentStatus",
"methodDescription": "手动更新Agent的状态",
"methodType": "POST",
"multipartKeyValueListJson": "[]",
"originUrl": "/octopus/server/status/agent/status/update",
"pathParamsKeyValueListJson": "[]",
"postScript": "",
"postType": "json",
"preScript": "",
"returnDocument": "{\n\t\"code\":\"No comment,Type =Number\",\n\t\"msg\":\"No comment,Type =String\",\n\t\"data\":{}\n}",
"tempId": "",
"url": "/octopus/server/status/agent/status/update",
"urlEncodedKeyValueListJson": "[]",
"urlEncodedKeyValueListText": "",
"urlParamsKeyValueListJson": "[]",
"urlParamsKeyValueListText": ""
},
"tempId": "id_io.wdd.rpc.controller.StatusController.ManualUpdateAgentStatus",
"type": 2
}

View File

@@ -0,0 +1,8 @@
{
"description": "",
"directory": "~.fastRequest~collections~Root~server~StatusController",
"filePath": "~.fastRequest~collections~Root~server~StatusController~",
"id": "20230222092955736",
"name": "StatusController",
"type": 3
}

View File

@@ -0,0 +1,8 @@
{
"description": "",
"directory": "~.fastRequest~collections~Root~server",
"filePath": "~.fastRequest~collections~Root~server~",
"id": "20221230113234995",
"name": "server",
"type": 4
}

View File

@@ -0,0 +1,37 @@
{
"dataList": [
{
"hostGroup": [
{
"env": "local",
"url": "localhost:9090"
}
],
"name": "OctpusGO"
}
],
"envList": [
"local"
],
"headerList": [],
"postScript": "",
"preScript": "",
"projectList": [
"OctpusGO"
],
"syncModel": {
"branch": "master",
"domain": "https://github.com",
"enabled": false,
"namingPolicy": "byDoc",
"owner": "",
"repo": "",
"repoUrl": "",
"syncAfterRun": false,
"token": "",
"type": "github"
},
"urlEncodedKeyValueList": [],
"urlParamsKeyValueList": [],
"urlSuffix": ""
}

View File

@@ -28,7 +28,7 @@ jobs:
with: with:
java-version: '11' java-version: '11'
distribution: 'temurin' distribution: 'temurin'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml server-id: github # Value of the distributionManagement/repository/id field of the pom.xml-back
settings-path: ${{ github.workspace }} # location for the settings.xml file settings-path: ${{ github.workspace }} # location for the settings.xml file
cache: maven cache: maven

View File

@@ -1,41 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Agent-Dev-LapPro-Ubuntu" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot">
<option name="ACTIVE_PROFILES" value="dev" />
<option name="ALTERNATIVE_JRE_PATH" value="11" />
<option name="DEBUG_MODE" value="true" />
<envs>
<env name="agentVersion" value="2023-02-13" />
<env name="archInfo" value="&quot;x86_64 (64 Bit)&quot;" />
<env name="cpuBrand" value="&quot;Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz&quot;" />
<env name="cpuCore" value="&quot;8 @ 4299.998 MHz&quot;" />
<env name="diskTotal" value="&quot;914.9 GB&quot;" />
<env name="diskUsage" value="&quot;12.3 GB&quot;" />
<env name="ioSpeed" value="&quot;259 MB/s&quot;" />
<env name="location" value="&quot;Chengdu Sichuan CN&quot;" />
<env name="machineId" value="&quot;ubuntu-lap-pro&quot;" />
<env name="managePort" value="&quot;22&quot;" />
<env name="memoryTotal" value="&quot;7.6 GB&quot;" />
<env name="osInfo" value="&quot;Ubuntu 20.04.5 LTS&quot;" />
<env name="osKernelInfo" value="&quot;5.4.0-135-generic&quot;" />
<env name="provider" value="&quot;AS139080 The Internet Data Center of Sichuan Mobile Communication Company Limited&quot;" />
<env name="server.port" value="8001" />
<env name="serverIpInV4" value="&quot;&quot;" />
<env name="serverIpInV6" value="&quot;&quot;" />
<env name="serverIpPbV4" value="&quot;183.220.149.17&quot;" />
<env name="serverIpPbV6" value="&quot;&quot;" />
<env name="serverName" value="&quot;Chengdu-amd64-71&quot;" />
<env name="tcpControl" value="&quot;cubic&quot;" />
<env name="virtualization" value="&quot;Dedicated&quot;" />
</envs>
<option name="HIDE_BANNER" value="true" />
<module name="agent" />
<option name="PASS_PARENT_ENVS" value="false" />
<projectPathOnTarget name="projectPathOnTarget" value="$PROJECT_DIR$" />
<option name="SPRING_BOOT_MAIN_CLASS" value="io.wdd.agent.AgentApplication" />
<option name="VM_PARAMETERS" value="-Dserver.port=8001 -Dfile.encoding=utf-8 -Ddebug=true -Dlogging.level.io.wdd.agent=debug -Dspring.profiles.active=dev -Dspring.cloud.nacos.config.group=dev -Dspring.cloud.nacos.config.extension-configs[0].dataId=common-dev.yaml -Dspring.cloud.nacos.config.extension-configs[0].group=dev" />
<method v="2">
<option name="ToolBeforeRunTask" enabled="true" actionId="Tool_External Tools_git pull code" />
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,36 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Agent-dev-1" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" activateToolWindowBeforeRun="false">
<option name="ALTERNATIVE_JRE_PATH" value="11" />
<envs>
<env name="agentVersion" value="2023-02-13" />
<env name="archInfo" value="&quot;x86_64 (64 Bit)&quot;" />
<env name="cpuBrand" value="&quot;Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz&quot;" />
<env name="cpuCore" value="&quot;12 @ 4299.998 MHz&quot;" />
<env name="diskTotal" value="&quot;914.9 GB&quot;" />
<env name="diskUsage" value="&quot;12.3 GB&quot;" />
<env name="ioSpeed" value="&quot;259 MB/s&quot;" />
<env name="location" value="&quot;Chengdu Sichuan CN&quot;" />
<env name="machineId" value="&quot;remote-dev-19&quot;" />
<env name="managePort" value="&quot;22&quot;" />
<env name="memoryTotal" value="&quot;7.6 GB&quot;" />
<env name="osInfo" value="&quot;Ubuntu 20.04.5 LTS&quot;" />
<env name="osKernelInfo" value="&quot;5.4.0-135-generic&quot;" />
<env name="provider" value="&quot;AS139080 The Internet Data Center of Sichuan Mobile Communication Company Limited&quot;" />
<env name="serverIpInV4" value="&quot;&quot;" />
<env name="serverIpInV6" value="&quot;&quot;" />
<env name="serverIpPbV4" value="&quot;183.220.149.17&quot;" />
<env name="serverIpPbV6" value="&quot;&quot;" />
<env name="serverName" value="&quot;Chengdu-amd64-77&quot;" />
<env name="tcpControl" value="&quot;cubic&quot;" />
<env name="virtualization" value="&quot;Dedicated&quot;" />
<env name="server.port" value="8001" />
</envs>
<module name="agent" />
<target name="UbuntuStation" />
<option name="SPRING_BOOT_MAIN_CLASS" value="io.wdd.agent.AgentApplication" />
<option name="VM_PARAMETERS" value="-Dserver.port=8001 -Dfile.encoding=utf-8 -Ddebug=true -Dlogging.level.io.wdd.agent=debug -Dspring.profiles.active=dev -Dspring.cloud.nacos.config.group=dev -Dspring.cloud.nacos.config.extension-configs[0].dataId=common-dev.yaml -Dspring.cloud.nacos.config.extension-configs[0].group=dev" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,37 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Agent-dev-oracle-s5" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot">
<option name="ALTERNATIVE_JRE_PATH" value="11" />
<envs>
<env name="agentVersion" value="2023-02-13" />
<env name="archInfo" value="&quot;x86_64 (64 Bit)&quot;" />
<env name="cpuBrand" value="Oracle Armpre A1" />
<env name="cpuCore" value="4 @2400MHz" />
<env name="diskTotal" value="100GB" />
<env name="diskUsage" value="&quot;12.3 GB&quot;" />
<env name="ioSpeed" value="&quot;259 MB/s&quot;" />
<env name="location" value="Seoul Seoul KR" />
<env name="machineId" value="oracles5dsaasdadas" />
<env name="managePort" value="22333" />
<env name="memoryTotal" value="&quot;7.6 GB&quot;" />
<env name="osInfo" value="&quot;Ubuntu 20.04.5 LTS&quot;" />
<env name="osKernelInfo" value="&quot;5.4.0-135-generic&quot;" />
<env name="provider" value="&quot;AS139080 The Internet Data Center of Sichuan Mobile Communication Company Limited&quot;" />
<env name="server.port" value="8001" />
<env name="serverIpInV4" value="&quot;&quot;" />
<env name="serverIpInV6" value="&quot;&quot;" />
<env name="serverIpPbV4" value="146.56.159.175" />
<env name="serverIpPbV6" value="&quot;&quot;" />
<env name="serverName" value="Seoul-arm64-02" />
<env name="tcpControl" value="bbr" />
<env name="virtualization" value="&quot;Dedicated&quot;" />
</envs>
<option name="HIDE_BANNER" value="true" />
<module name="agent" />
<option name="SPRING_BOOT_MAIN_CLASS" value="io.wdd.agent.AgentApplication" />
<option name="VM_PARAMETERS" value="-Dserver.port=8001 -Dfile.encoding=utf-8 -Ddebug=true -Dlogging.level.io.wdd.agent=debug -Dspring.profiles.active=dev -Dspring.cloud.nacos.config.group=dev -Dspring.cloud.nacos.config.extension-configs[0].dataId=common-dev.yaml -Dspring.cloud.nacos.config.extension-configs[0].group=dev" />
<method v="2">
<option name="ToolBeforeRunTask" enabled="true" actionId="Tool_External Tools_git pull" />
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,32 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="RunServerToRemote" type="docker-deploy" factoryName="dockerfile"
server-name="Oracle-Seoul-0">
<deployment type="dockerfile">
<settings>
<option name="imageTag" value="remote-idea"/>
<option name="containerName" value="octopus-server-idea"/>
<option name="portBindings">
<list>
<DockerPortBindingImpl>
<option name="containerPort" value="9999"/>
<option name="hostPort" value="9999"/>
</DockerPortBindingImpl>
</list>
</option>
<option name="sourceFilePath" value="server/Dockerfile-shanghai-remote-idea"/>
<option name="volumeBindings">
<list>
<DockerVolumeBindingImpl>
<option name="containerPath" value="/octopus-server"/>
<option name="hostPath" value="/octopus-server"/>
</DockerVolumeBindingImpl>
</list>
</option>
</settings>
</deployment>
<method v="2">
<option name="RunConfigurationTask" enabled="true" run_configuration_name="SkipTest-Package"
run_configuration_type="MavenRunConfiguration"/>
</method>
</configuration>
</component>

View File

@@ -1,16 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Server-dev" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" activateToolWindowBeforeRun="false">
<option name="DEBUG_MODE" value="true"/>
<option name="HIDE_BANNER" value="true" />
<module name="server" />
<selectedOptions>
<option name="spring.boot.profiles" visible="false" />
</selectedOptions>
<option name="SPRING_BOOT_MAIN_CLASS" value="io.wdd.ServerApplication" />
<option name="VM_PARAMETERS"
value="-Ddebug=true -Dlogging.level.io.wdd.server=debug -Dfile.encoding=utf-8 -Dspring.profiles.active=dev -Dspring.cloud.nacos.config.group=dev -Dspring.cloud.nacos.config.extension-configs[0].dataId=common-dev.yaml -Dspring.cloud.nacos.config.extension-configs[0].group=dev"/>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,13 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Server-k3s" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot">
<module name="server" />
<selectedOptions>
<option name="spring.boot.profiles" visible="false" />
</selectedOptions>
<option name="SPRING_BOOT_MAIN_CLASS" value="io.wdd.ServerApplication" />
<option name="VM_PARAMETERS" value="-Dfile.encoding=utf-8 -Dspring.profiles.active=k3s -Dspring.cloud.nacos.config.group=k3s -Dspring.cloud.nacos.config.extension-configs[0].dataId=common-k3s.yaml -Dspring.cloud.nacos.config.extension-configs[0].group=k3s" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,31 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="SkipTest-Package" type="MavenRunConfiguration" factoryName="Maven">
<MavenSettings>
<option name="myGeneralSettings"/>
<option name="myRunnerSettings"/>
<option name="myRunnerParameters">
<MavenRunnerParameters>
<option name="profiles">
<set/>
</option>
<option name="goals">
<list>
<option value="clean"/>
<option value="-DskipTests=true"/>
<option value="package"/>
</list>
</option>
<option name="pomFileName"/>
<option name="profilesMap">
<map>
<entry key="pom.xml" value="true"/>
</map>
</option>
<option name="resolveToWorkspace" value="false"/>
<option name="workingDirPath" value="$PROJECT_DIR$"/>
</MavenRunnerParameters>
</option>
</MavenSettings>
<method v="2"/>
</configuration>
</component>

View File

@@ -0,0 +1,216 @@
package main
import (
"agent-go/executor"
"agent-go/g"
"agent-go/rabbitmq"
"agent-go/register"
"encoding/json"
"fmt"
"gopkg.in/yaml.v3"
"io/ioutil"
"time"
)
var omType = g.InitOmType
var P = g.G.P
var AgentServerInfoCache = &register.AgentServerInfo{}
func INIT() *register.AgentServerInfo {
// 获取系统的环境变量
agentServerInfo := parseAgentServerInfo()
agentConfig := g.G.AgentConfig
initToServerProp := &rabbitmq.ConnectProperty{
ExchangeName: agentConfig.GetString("octopus.message.init_exchange"),
QueueName: agentConfig.GetString("octopus.message.init_to_server"),
ExchangeType: g.QueueDirect,
TopicKey: agentConfig.GetString("octopus.message.init_to_server_key"),
}
initFromServerProp := &rabbitmq.ConnectProperty{
ExchangeName: agentConfig.GetString("octopus.message.init_exchange"),
QueueName: agentConfig.GetString("octopus.message.init_from_server"),
ExchangeType: g.QueueDirect,
TopicKey: agentConfig.GetString("octopus.message.init_from_server_key"),
}
// 建立RabbitMQ的连接
initToServerQueue := &rabbitmq.RabbitQueue{
RabbitProp: initToServerProp,
}
defer initToServerQueue.Close()
// 建立连接
initToServerQueue.Connect()
// 组装OctopusMessage
var octopusMsg *rabbitmq.OctopusMessage
octopusMsg = octopusMsg.Build(
omType,
agentServerInfo,
)
msgBytes, err := json.Marshal(octopusMsg)
if err != nil {
log.Error(fmt.Sprintf("octopus message convert to json is wrong! msg is => %v", octopusMsg))
}
// 发送OM至MQ中
P.Submit(
func() {
for g.G.AgentHasRegister == false {
log.Debug(fmt.Sprintf("Send init message to server! ==> %s", string(msgBytes)))
//如果agent存活 而Server不存活 那么需要持续不断的向Server中发送消息
initToServerQueue.Send(
msgBytes,
)
// 休眠
time.Sleep(10 * time.Minute)
}
})
// 监听初始化连接中的信息
initFromServerQueue := &rabbitmq.RabbitQueue{
RabbitProp: initFromServerProp,
}
//defer initFromServerQueue.Close()
// 建立连接
initFromServerQueue.Connect()
// 建立运行时RabbitMQ连接
handleInitMsgFromServer(initFromServerQueue, initToServerQueue, agentServerInfo)
return agentServerInfo
}
// handleInitMsgFromServer 处理从Server接收的 注册信息
func handleInitMsgFromServer(initFromServerQueue *rabbitmq.RabbitQueue, initToServerQueue *rabbitmq.RabbitQueue, agentServerInfo *register.AgentServerInfo) {
initOctopusMessageDeliveries := initFromServerQueue.Read(false)
// 2023年6月19日 修复注册信息一直没有完全消费的问题
findRealAgentTopicName := ""
// 同步很多抢占注册的情况
for delivery := range initOctopusMessageDeliveries {
log.Debug(fmt.Sprintf("message received from server is %s", string(delivery.Body)))
var initOctopusMsg *rabbitmq.OctopusMessage
err := json.Unmarshal(delivery.Body, &initOctopusMsg)
if err != nil {
log.Error(fmt.Sprintf("parse init message from server wroong, message is => %s ",
string(delivery.Body)))
}
var serverInfo register.AgentServerInfo
s, er := initOctopusMsg.Content.(string)
if !er {
log.ErrorF("convet to string error! => %v", er)
}
cc := json.Unmarshal([]byte(s), &serverInfo)
if cc != nil {
log.Error(fmt.Sprintf("parse init message from server wroong, message is => %v ", cc))
}
serverName := serverInfo.ServerName
// 处理OM信息
if initOctopusMsg != nil && initOctopusMsg.Type == g.InitOmType && serverName == agentServerInfo.ServerName {
// 是本机的注册回复信息
log.InfoF("OctopusMessage INIT from server is this agent !")
// 手动确认信息
delivery.Ack(false)
// 修改系统参数
g.G.AgentHasRegister = true
// 保存真实的AgentTopicName
findRealAgentTopicName = serverInfo.TopicName
// 手动关闭 注册队列的连接
shutdownRegisterQueueConnection(initFromServerQueue, initToServerQueue)
} else {
// 不是自身的 注册回复信息 -- 拒绝 2023年6月19日 此处存在错误! 会死循环Nack 导致异常
log.Warn(fmt.Sprintf("OctopusMessage INIT from server not this agent ! => %v, ==>%s", initOctopusMsg, delivery.Body))
delivery.Ack(false)
// 需要休眠等待不再获取相应的信息
time.Sleep(5 * time.Second)
}
}
// 建立 运行时 RabbitMQ连接
rabbitmq.BuildOMsgRuntimeConnectorQueue(findRealAgentTopicName)
}
// shutdownRegisterQueueConnection 关闭初始化连接的两个队列
func shutdownRegisterQueueConnection(initFromServerQueue *rabbitmq.RabbitQueue, initToServerQueue *rabbitmq.RabbitQueue) {
initFromServerQueue.Close()
initToServerQueue.Close()
log.InfoF("Pretend to Shutdown register queue connection !")
}
func parseAgentServerInfo() *register.AgentServerInfo {
// 约定文件地址为 /etc/environment.d/octopus-agent.conf
// 目前使用
var agentServerInfo *register.AgentServerInfo
//yamlFile, err := ioutil.ReadFile("C:\\Users\\wdd\\IdeaProjects\\ProjectOctopus\\agent-go\\server-env.yaml")
yamlFile, err := ioutil.ReadFile("server-env.yaml")
if err != nil {
panic(fmt.Errorf("failed to read YAML file: %v", err))
}
err = yaml.Unmarshal(yamlFile, &agentServerInfo)
if err != nil {
panic(fmt.Errorf("failed to unmarshal YAML: %v", err))
}
jsonFormat, err := json.Marshal(agentServerInfo)
if err != nil {
log.Error(fmt.Sprintf("agent server info convert error ! agentserverinfo is %v", agentServerInfo))
panic(err)
}
log.Info(fmt.Sprintf("agent server info is %v", string(jsonFormat)))
// build a operator cache
BuildAgentOsOperator(agentServerInfo)
return agentServerInfo
}
func BuildAgentOsOperator(agentServerInfo *register.AgentServerInfo) {
executor.AgentOsOperatorCache = &executor.AgentOsOperator{
InstallCommandPrefix: []string{
"apt-get", "install", "-y",
},
RemoveCommandPrefix: []string{"apt", "remove", "-y"},
CanAccessInternet: true,
IsOsTypeUbuntu: true,
IsAgentInnerWall: true,
AgentArch: "amd64",
AgentOSReleaseCode: "focal",
AgentServerInfo: agentServerInfo,
}
// debug
marshal, _ := json.Marshal(executor.AgentOsOperatorCache)
log.DebugF("cached agent operator is %s", marshal)
}

View File

@@ -1,11 +0,0 @@
package main
/*type RabbitSendWriter interface {
Send(conn *RabbitMQConn, connProp *ConnectProperty, message []byte)
Read(conn *RabbitMQConn, connProp *ConnectProperty, autoAck bool) <-chan amqp.Delivery
}
*/

View File

@@ -1,50 +0,0 @@
package config
import (
"agent-go/utils"
"encoding/json"
"fmt"
"time"
)
type OctopusMessage struct {
UUID string `json:"uuid"`
InitTime time.Time `json:"init_time" format:"2023-03-21 16:38:30"`
Type string `json:"type"`
Content interface{} `json:"content"`
Result interface{} `json:"result"`
ACTime time.Time `json:"ac_time" format:"2023-03-21 16:38:30"`
}
type ExecutionMessage struct {
NeedResultReplay bool `json:"needResultReplay"`
DurationTask bool `json:"durationTask,default:false"`
Type string `json:"type"`
SingleLineCommand []string `json:"singleLineCommand"`
MultiLineCommand [][]string `json:"multiLineCommand"`
PipeLineCommand [][]string `json:"pipeLineCommand"`
ResultKey string `json:"resultKey"`
}
// BuildOctopusMsg 生成OctopusMessage
func (m *OctopusMessage) BuildOctopusMsg(omType string, content interface{}) *OctopusMessage {
// 当前时间
curTimeString := utils.CurTimeString()
// must write to string format, otherwise it's very hard to deserialize
bytes, err := json.Marshal(content)
if err != nil {
fmt.Sprintf("OctopusMessage Build Error ! %v", err)
}
return &OctopusMessage{
UUID: curTimeString,
InitTime: time.Now(),
Type: omType,
Content: string(bytes),
Result: nil,
ACTime: time.Time{},
}
}

View File

@@ -0,0 +1,780 @@
package executor
import (
"agent-go/g"
"agent-go/register"
"fmt"
"strings"
)
type BaseFunc interface {
Exec(baseFuncName string, funcArgs ...string) []string
}
type AgentOsOperator struct {
InstallCommandPrefix []string `json:"install_command_prefix",comment:"apt-get install or yum install"`
RemoveCommandPrefix []string `json:"remove_command_prefix",comment:"apt-get remove or yum remove"`
CanAccessInternet bool `json:"can_access_internet",comment:"是否可以访问公网"`
IsOsTypeUbuntu bool `json:"is_os_type_ubuntu",comment:"主机操作系统是否为ubuntu系列"`
IsAgentInnerWall bool `json:"is_agent_inner_wall",comment:"主机是否身处国内"`
AgentArch string `json:"agent_arch",comment:"主机的CPU架构可选为amd64 arm64"`
AgentOSReleaseCode string `json:"agent_os_release_code",comment:"主机操作系统的发行版代号, focal之类的"`
AgentServerInfo *register.AgentServerInfo `json:"agent_server_info"`
}
// Exec 执行基础功能函数
func (op *AgentOsOperator) Exec(baseFuncName string, funcArgs ...string) []string {
var multiLineCommand [][]string
switch baseFuncName {
case "shutdownFirewall":
multiLineCommand = op.shutdownFirewall()
break
case "modifyHostname":
multiLineCommand = op.modifyHostname(funcArgs)
break
case "enableSwap":
multiLineCommand = op.enableSwap()
break
case "disableSwap":
multiLineCommand = op.disableSwap()
break
case "installDocker":
multiLineCommand = op.installDocker(funcArgs)
break
case "removeDocker":
multiLineCommand = op.removeDocker()
break
case "removeDockerCompose":
multiLineCommand = op.removeDockerCompose()
break
case "installDockerCompose":
multiLineCommand = op.installDockerCompose()
break
case "modifyDockerConfig":
multiLineCommand = op.modifyDockerConfig(funcArgs)
break
case "installHelm":
multiLineCommand = op.installHelm()
break
case "installHarbor":
multiLineCommand = op.installHarbor()
break
case "chronyToPublicNTP":
multiLineCommand = op.chronyToPublicNTP()
break
case "chronyToMaster":
multiLineCommand = op.chronyToMaster(funcArgs)
break
case "installZSH":
multiLineCommand = op.installZSH()
break
case "modifySshPort":
multiLineCommand = op.modifySshPort(funcArgs)
break
case "openBBR":
multiLineCommand = op.openBBR()
break
default:
multiLineCommand = op.ok(funcArgs)
}
log.DebugF("multiLineCommand are => %v", multiLineCommand)
var result []string
// exec the command here
for _, singleLineCommand := range multiLineCommand {
result = append(result, AllOutputCommandExecutor(singleLineCommand)...)
// debug usage
log.DebugF("exec result are => %v", result)
for _, logLine := range result {
fmt.Println(logLine)
}
}
// 归一化处理
return result
}
func (op *AgentOsOperator) shutdownFirewall() [][]string {
shutdownFunc := [][]string{
{"systemctl", "stop", "firewalld"},
{"systemctl", "disable", "firewalld"},
}
if !op.IsOsTypeUbuntu {
shutdownFunc = append(shutdownFunc,
[]string{
"sed",
"-i",
"s/SELINUX=enforcing/SELINUX=disabled/g",
"/etc/selinux/config",
},
)
}
return shutdownFunc
}
func (op *AgentOsOperator) modifyHostname(args []string) [][]string {
return [][]string{}
}
func (op *AgentOsOperator) enableSwap() [][]string {
enableSwapFunc := [][]string{
{
"cp",
"-f",
"/etc/fstab_back",
"/etc/fstab",
},
{
"cat",
"/etc/fstab",
},
}
return enableSwapFunc
}
func (op *AgentOsOperator) disableSwap() [][]string {
disableSwapFunc := [][]string{
{
"swapoff",
"-a",
},
{
"cp",
"-f",
"/etc/fstab",
"/etc/fstab_back",
},
{
"sed",
"-i",
"/swap/d",
"/etc/fstab",
},
}
return disableSwapFunc
}
func (op *AgentOsOperator) removeDocker() [][]string {
removeDockerLine := append(op.RemoveCommandPrefix, []string{
"docker-ce",
"docker.io",
"docker-ce-cli",
//"docker",
//"docker-common",
//"docker-latest",
//"docker-latest-logrotate",
//"docker-logrotate",
//"docker-selinux",
//"docker-engine-selinux",
//"docker-engine",
//"kubelet",
//"kubeadm",
//"kubectl",
//"docker-client",
//"docker-client-latest",
}...)
removeDockerFunc := [][]string{
removeDockerLine,
}
return removeDockerFunc
}
func (op *AgentOsOperator) installDocker(args []string) [][]string {
// remove docker all staff
installDockerFunc := op.removeDocker()
if op.IsOsTypeUbuntu {
//
installFirstLine := append(op.InstallCommandPrefix, []string{
"apt-transport-https",
"ca-certificates",
"curl",
"gnupg-agent",
"software-properties-common",
}...)
if op.IsAgentInnerWall {
// inner gfw
installDockerFunc = append(installDockerFunc, [][]string{
installFirstLine,
{
"curl",
"-o",
"/usr/share/keyrings/docker-utsc.gpg",
"https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg",
},
{
"apt-key",
"add",
"/usr/share/keyrings/docker-utsc.gpg",
},
{
"add-apt-repository",
"deb [arch=" + op.AgentArch + "] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu " + op.AgentOSReleaseCode + " stable",
},
}...)
} else {
// outside world
installDockerFunc = append(installDockerFunc, [][]string{
installFirstLine,
{
"curl",
"-o",
"/usr/share/keyrings/docker.gpg",
"https://download.docker.com/linux/ubuntu/gpg ",
},
{
"apt-key",
"add",
"/usr/share/keyrings/docker.gpg",
},
{
"add-apt-repository",
"deb [arch=" + op.AgentArch + "] https://download.docker.com/linux/ubuntu " + op.AgentOSReleaseCode + " stable",
},
}...)
}
// look for specific docker-version to install
installDockerFunc = append(installDockerFunc, []string{"apt-get", "update"})
var specificDockerVersion string
// hard code here 5:20.10.10~3-0~ubuntu-focal
if strings.HasPrefix(args[0], "19") {
specificDockerVersion = "5:19.03.15~3-0~ubuntu-" + op.AgentOSReleaseCode
} else {
specificDockerVersion = "5:20.10.10~3-0~ubuntu-" + op.AgentOSReleaseCode
}
installDockerFunc = append(installDockerFunc,
append(
op.InstallCommandPrefix,
"docker-ce="+specificDockerVersion,
"docker-ce-cli="+specificDockerVersion,
"containerd.io",
"docker-compose-plugin",
),
)
} else {
installFirstLine := append(op.InstallCommandPrefix,
[]string{
"yum-utils",
"device-mapper-persistent-data",
"lvm2",
}...,
)
if op.IsAgentInnerWall {
// inner gfw
installDockerFunc = append(installDockerFunc, [][]string{
installFirstLine,
{
"yum-config-manager",
"--add-repo",
"https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo",
},
{
"sed ",
"-i ",
"'s/download.docker.com/mirrors.ustc.edu.cn\\/docker-ce/g' ",
"/etc/yum.repos.d/docker-ce.repo",
},
{},
}...)
} else {
// outside world
}
}
return installDockerFunc
}
func (op *AgentOsOperator) removeDockerCompose() [][]string {
installDockerComposeFunc := [][]string{
append(
op.RemoveCommandPrefix,
"docker-compose",
),
}
return installDockerComposeFunc
}
func (op *AgentOsOperator) installDockerCompose() [][]string {
installDockerComposeFunc := [][]string{
append(
op.InstallCommandPrefix,
"docker-compose",
),
}
return installDockerComposeFunc
}
func (op *AgentOsOperator) installHelm() [][]string {
installHelmFunc := [][]string{
{
"mkdir",
"-p",
"/root/wdd/",
},
{
"rm",
"-rf",
"/root/wdd/helm-v*",
},
{
"rm",
"-rf",
"/root/wdd/linux-amd64",
},
{
"wget",
"--no-check-certificate",
g.BaseFuncOssUrlPrefix + "helm-v3.12.1-linux-amd64.tar.gz",
"-O",
"/root/wdd/helm-v3.12.1-linux-amd64.tar.gz",
},
{
"tar",
"-zvxf",
"/root/wdd/helm-v3.12.1-linux-amd64.tar.gz",
},
{
"chmod",
"+x",
"/root/wdd/linux-amd64/helm",
},
{
"mv",
"/root/wdd/linux-amd64/helm",
"/usr/local/bin/helm",
},
{
"helm",
"version",
},
}
/*if op.IsOsTypeUbuntu {
installHelmFunc = [][]string{
{
"curl",
"-o",
"/usr/share/keyrings/helm.gpg",
"https://baltocdn.com/helm/signing.asc",
},
{
"apt-key",
"add",
"/usr/share/keyrings/helm.gpg",
},
{
"add-apt-repository",
"https://baltocdn.com/helm/stable/debian/ all main",
},
{
"apt-get",
"update",
},
append(op.InstallCommandPrefix, "helm"),
}
} else {
log.ErrorF("Operation OS is CentOS, Helm not installed!")
}*/
return installHelmFunc
}
func (op *AgentOsOperator) modifyDockerConfig(args []string) [][]string {
harborIPAddr := args[0] + ":8033"
modifyDockerConfigFunc := [][]string{
{
"mv",
"/etc/docker/daemon.json",
"/etc/docker/daemon.backup.json",
},
{
"wget",
g.BaseFuncOssUrlPrefix + "daemon-config.json",
"-O",
"/etc/docker/daemon.json",
},
{
"sed",
"-i",
"s/$DockerRegisterDomain/" + harborIPAddr + "/g",
"/etc/docker/daemon.json",
},
{
"systemctl",
"restart",
"docker.service",
},
}
return modifyDockerConfigFunc
}
func (op *AgentOsOperator) installHarbor() [][]string {
installHarborFunc := [][]string{
//{
// "mkdir",
// "-p",
// "/root/wdd/",
//},
//{
// "rm",
// "-rf",
// "/root/wdd/harbor-offline-installer-v2.1.0.tgz",
//},
//{
// "wget",
// "--no-check-certificate",
// g.BaseFuncOssUrlPrefix + "harbor-offline-installer-v2.1.0.tgz",
// "-O",
// "/root/wdd/harbor-offline-installer-v2.1.0.tgz",
//},
{
"tar",
"-zvxf",
"/root/wdd/harbor-offline-installer-v2.1.0.tgz",
"-C",
"/root/wdd/",
},
{
"rm",
"-rf",
"/root/wdd/harbor/harbor.yml",
},
{
"wget",
"--no-check-certificate",
g.BaseFuncOssUrlPrefix + "harbor-config-template.yml",
"-O",
"/root/wdd/harbor/harbor.yml",
},
{
"sed",
"-i",
"s/$HarborHostName/" + op.AgentServerInfo.ServerIPInV4 + "/g",
"/root/wdd/harbor/harbor.yml",
},
{
"sed",
"-i",
"s/$HarborHostPort/8033/g",
"/root/wdd/harbor/harbor.yml",
},
{
"sed",
"-i",
"s/$HarborHostPort/V2ryStr@ngPss/g",
"/root/wdd/harbor/harbor.yml",
},
{
"/root/wdd/harbor/install.sh",
"--with-chartmuseum",
},
}
return installHarborFunc
}
func (op *AgentOsOperator) chronyToPublicNTP() [][]string {
serverIPInV4 := op.AgentServerInfo.ServerIPInV4
internalIPCIDR := strings.Join(strings.Split(serverIPInV4, ".")[:2], ".") + ".0.0/16"
chronyToPublicNTPFunc := [][]string{
append(
op.InstallCommandPrefix,
"chrony",
),
{
"systemctl",
"enable",
"chronyd",
},
{
"systemctl",
"start",
"chronyd",
},
}
var chronyFile string
if op.IsOsTypeUbuntu {
chronyFile = "/etc/chrony/chrony.conf"
} else {
chronyFile = "/etc/chrony.conf"
}
chronyToPublicNTPFunc = append(chronyToPublicNTPFunc,
[][]string{
{
"sed",
"-i",
"$ a allow " + internalIPCIDR,
chronyFile,
},
{
"sed",
"-i",
"s/pool ntp.ubuntu.com iburst/server ntp2.aliyun.com iburst/g",
chronyFile,
},
{
"systemctl",
"restart",
"chronyd",
},
{
"sleep",
"2",
},
{
"chronyc",
"-n",
"sources",
"-v",
},
{
"chronyc",
"tracking",
},
{
"timedatectl",
"set-timezone",
"Asia/Shanghai",
},
{
"timedatectl",
"set-ntp",
"true",
},
{
"systemctl",
"restart",
"rsyslog",
},
}...,
)
return chronyToPublicNTPFunc
}
func (op *AgentOsOperator) chronyToMaster(args []string) [][]string {
masterInnerIP := args[0]
chronyToMasterFunc := [][]string{
{
"sed",
"-i",
"$ a NTP=" + masterInnerIP,
"/etc/systemd/timesyncd.conf",
},
{
"systemctl",
"daemon-reload",
},
{
"systemctl",
"restart",
"systemd-timesyncd.service",
},
{
"sleep",
"3",
},
{
"timedatectl",
"show-timesync",
"--all",
},
{
"timedatectl",
"status",
},
}
return chronyToMasterFunc
}
func (op *AgentOsOperator) installZSH() [][]string {
installZSHFunc := [][]string{
{
"mkdir",
"-p",
"/root/wdd/",
},
append(
op.InstallCommandPrefix,
"zsh",
"git",
),
}
if op.IsAgentInnerWall {
installZSHFunc = append(
installZSHFunc,
[][]string{
{
"wget",
"https://cdn.jsdelivr.net/gh/robbyrussell/oh-my-zsh@master/tools/install.sh",
"-O",
"/root/wdd/zsh-install.sh",
},
}...,
)
} else {
installZSHFunc = append(
installZSHFunc,
[][]string{
{
"wget",
"https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh",
"-O",
"/root/wdd/zsh-install.sh",
},
}...,
)
}
// install
installZSHFunc = append(
installZSHFunc,
[][]string{
{
"chmod",
"+x",
"/root/wdd/zsh-install.sh",
},
{
"sh",
"-c",
"/root/wdd/zsh-install.sh",
},
}...,
)
// modify ZSH
if !op.IsAgentInnerWall {
installZSHFunc = append(
installZSHFunc,
[][]string{
{
"git",
"clone",
"https://github.com.cnpmjs.org/zsh-users/zsh-autosuggestions",
"~/.oh-my-zsh/plugins/zsh-autosuggestions",
},
{
"git",
"clone",
"https://github.com.cnpmjs.org/zsh-users/zsh-syntax-highlighting.git",
"~/.oh-my-zsh/plugins/zsh-syntax-highlighting",
},
{
"wget",
"https://b2.107421.xyz/oh-my-zsh-plugins-list.txt",
"-O",
"oh-my-zsh-plugins-list.txt",
},
{
"wget",
"-c",
"-i",
"./oh-my-zsh-plugins-list.txt",
"-P",
"~/.oh-my-zsh/plugins/",
},
{
"sed",
"-i",
"s/robbyrussell/agnoster/g",
"~/.zshrc",
},
{
"sed",
"-i",
"s/^# DISABLE_AUTO_UPDATE=\"true\"/DISABLE_AUTO_UPDATE=\"true\"/g",
"~/.zshrc",
},
{
"sed",
"-i",
"s/plugins=(git)/plugins=(git zsh-autosuggestions zsh-syntax-highlighting command-not-found z themes)/g",
"~/.zshrc",
},
{
"source",
"~/.zshrc",
},
{
"chsh",
"-s",
"/bin/zsh",
},
{
"zsh",
},
}...,
)
}
return installZSHFunc
}
func (op *AgentOsOperator) modifySshPort(args []string) [][]string {
return [][]string{}
}
func (op *AgentOsOperator) openBBR() [][]string {
return [][]string{}
}
func (op *AgentOsOperator) ok(args []string) [][]string {
log.InfoF("base function is ok , args are => " + strings.Join(args, " "))
return [][]string{
{"ifconfig"},
}
}

View File

@@ -0,0 +1,60 @@
package executor
import (
"agent-go/register"
"testing"
)
var agentOP = &AgentOsOperator{
InstallCommandPrefix: []string{
"apt-get", "install", "-y",
},
RemoveCommandPrefix: []string{"apt", "remove", "-y"},
CanAccessInternet: true,
IsOsTypeUbuntu: true,
IsAgentInnerWall: true,
AgentArch: "amd64",
AgentOSReleaseCode: "focal",
AgentServerInfo: &register.AgentServerInfo{
ServerName: "",
ServerIPPbV4: "",
ServerIPInV4: "192.168.0.8",
ServerIPPbV6: "",
ServerIPInV6: "",
Location: "",
Provider: "",
ManagePort: "",
CPUCore: "",
CPUBrand: "",
OSInfo: "",
OSKernelInfo: "",
TCPControl: "",
Virtualization: "",
IoSpeed: "",
MemoryTotal: "",
DiskTotal: "",
DiskUsage: "",
Comment: "",
MachineID: "",
AgentVersion: "",
TopicName: "",
},
}
func TestBaseFunc(t *testing.T) {
//agentOP.Exec("shutdownFirewall")
//agentOP.Exec("modifyHostname")
//agentOP.Exec("disableSwap")
//agentOP.Exec("enableSwap")
//agentOP.Exec("removeDocker")
agentOP.Exec("installDocker", "20")
//agentOP.Exec("removeDockerCompose")
//agentOP.Exec("installDockerCompose")
//agentOP.Exec("installHelm")
//agentOP.Exec("installHarbor")
//agentOP.Exec("chronyToPublicNTP")
//agentOP.Exec("chronyToMaster", "192.168.0.8")
//agentOP.Exec("installZSH")
}

View File

@@ -1,31 +1,56 @@
package executor package executor
import ( import (
"agent-go/config" logger2 "agent-go/logger"
"agent-go/g"
"bufio" "bufio"
"bytes" "bytes"
"fmt" "fmt"
"os/exec" "os/exec"
"time" "strings"
) )
var log = g.G.LOG type ExecutionMessage struct {
NeedResultReplay bool `json:"needResultReplay"`
DurationTask bool `json:"durationTask,default:false"`
Type string `json:"type"`
BaseFuncContent []string `json:"baseFuncContent"`
SingleLineCommand []string `json:"singleLineCommand"`
MultiLineCommand [][]string `json:"multiLineCommand"`
PipeLineCommand [][]string `json:"pipeLineCommand"`
ResultKey string `json:"resultKey"`
}
func Execute(om *config.OctopusMessage, em *config.ExecutionMessage) ([]string, error) { var log = logger2.Log
var AgentOsOperatorCache = &AgentOsOperator{}
func Execute(em *ExecutionMessage) ([]string, error) {
var resultLog []string var resultLog []string
var err error var err error
var realCommand [][]string
if strings.HasPrefix(em.Type, "BASE") {
// base function
resultLog = AgentOsOperatorCache.Exec(em.BaseFuncContent[0], em.BaseFuncContent[1:]...)
err = nil
if em.PipeLineCommand != nil && len(em.PipeLineCommand) != 0 {
// 管道命令
resultLog, err = PipeLineCommandExecutor(em.PipeLineCommand)
} else if em.MultiLineCommand != nil && len(em.MultiLineCommand) != 0 {
// 多行命令
resultLog, err = MultiLineCommandExecutor(em.MultiLineCommand)
} else { } else {
// 单行命令 // shell command
resultLog, err = SingleLineCommandExecutor(em.SingleLineCommand)
if em.PipeLineCommand != nil && len(em.PipeLineCommand) != 0 {
// 管道命令
resultLog, err = PipeLineCommandExecutor(em.PipeLineCommand)
realCommand = em.PipeLineCommand
} else if em.MultiLineCommand != nil && len(em.MultiLineCommand) != 0 {
// 多行命令
resultLog, err = MultiLineCommandExecutor(em.MultiLineCommand)
realCommand = em.MultiLineCommand
} else {
// 单行命令
resultLog, err = SingleLineCommandExecutor(em.SingleLineCommand)
realCommand = [][]string{em.SingleLineCommand}
}
} }
// 归一化错误和日志 // 归一化错误和日志
@@ -33,69 +58,40 @@ func Execute(om *config.OctopusMessage, em *config.ExecutionMessage) ([]string,
resultLog = append(resultLog, fmt.Sprintf("Error: %s", err.Error())) resultLog = append(resultLog, fmt.Sprintf("Error: %s", err.Error()))
} }
// 处理执行日志 commandResult := fmt.Sprintf("Excution Comand are=> %v, Executor Result: %v", realCommand, resultLog)
// 是否需要返回处理日志,现在默认返回
if em.NeedResultReplay {
// 需要返回处理结果
om.ACTime = time.Now()
om.Result = resultLog
}
log.Info(fmt.Sprintf("Executor Result: %s", resultLog)) log.Info(commandResult)
return resultLog, err return resultLog, err
} }
func PipeLineCommandExecutor(pipeLineCommand [][]string) ([]string, error) { func PipeLineCommandExecutor(pipeLineCommand [][]string) ([]string, error) {
var cmds []*exec.Cmd var output []byte
var err error
// 创建每个命令对象,并将前一个命令的标准输出连接到当前命令的标准输入 for i, command := range pipeLineCommand {
for i, partOfCommand := range pipeLineCommand { cmd := exec.Command(command[0], command[1:]...)
cmd := exec.Command(partOfCommand[0], partOfCommand[1:]...) cmd.Stdin = bytes.NewReader(output)
if i > 0 { output, err = cmd.Output()
prevCmd := cmds[i-1] if err != nil {
out, err := prevCmd.StdoutPipe() return strings.Split(string(output), "\n"), err
if err != nil { }
return nil, err if i == len(pipeLineCommand)-1 {
} return strings.Split(string(output), "\n"), nil
cmd.Stdin = out
} }
cmds = append(cmds, cmd)
} }
return []string{}, nil
// 执行最后一个命令,并获取其输出
lastCmd := cmds[len(cmds)-1]
var out bytes.Buffer
lastCmd.Stdout = &out
lastCmd.Stderr = &out
err := lastCmd.Run()
scanner := bufio.NewScanner(&out)
var result []string
for scanner.Scan() {
result = append(result, scanner.Text())
}
if err != nil {
return nil, err
}
return result, nil
} }
func MultiLineCommandExecutor(multiLineCommandExecutor [][]string) ([]string, error) { func MultiLineCommandExecutor(multiLineCommandExecutor [][]string) ([]string, error) {
var res []string var res []string
for _, singleLineCommand := range multiLineCommandExecutor { for _, singleLineCommand := range multiLineCommandExecutor {
singleLogs, err := SingleLineCommandExecutor(singleLineCommand) singleLogs, err := SingleLineCommandExecutor(singleLineCommand)
res := append(res, singleLogs...) res = append(res, singleLogs...)
if err != nil { if err != nil {
log.Error(fmt.Sprintf("Execution error ! command is %v, error is %v", singleLineCommand, err))
return res, err return res, err
} }
@@ -118,7 +114,6 @@ func SingleLineCommandExecutor(singleLineCommand []string) ([]string, error) {
var result []string var result []string
for scanner.Scan() { for scanner.Scan() {
result = append(result, scanner.Text()) result = append(result, scanner.Text())
} }
if err != nil { if err != nil {

View File

@@ -0,0 +1,81 @@
package executor
import (
"bufio"
"fmt"
"io"
"os/exec"
)
func ReadTimeCommandExecutor(singleLineCommand []string) {
cmd := exec.Command(singleLineCommand[0], singleLineCommand[1:]...)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.ErrorF("command %v stdout error => %v", singleLineCommand, err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.ErrorF("command %v stderr error => %v", singleLineCommand, err)
}
if err := cmd.Start(); err != nil {
log.ErrorF("command %v runtime error => %v", singleLineCommand, err)
}
go realTimeOutput(stdout)
go realTimeOutput(stderr)
if err := cmd.Wait(); err != nil {
log.ErrorF("command %v result error => %v", singleLineCommand, err)
}
}
func AllOutputCommandExecutor(singleLineCommand []string) []string {
cmd := exec.Command(singleLineCommand[0], singleLineCommand[1:]...)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.ErrorF("command %v stdout error => %v", singleLineCommand, err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.ErrorF("command %v stderr error => %v", singleLineCommand, err)
}
if err := cmd.Start(); err != nil {
log.ErrorF("command %v runtime error => %v", singleLineCommand, err)
}
var resultSlice []string
resultSlice = append(resultSlice, collectOutput(stdout, resultSlice)...)
resultSlice = append(resultSlice, collectOutput(stderr, resultSlice)...)
if err := cmd.Wait(); err != nil {
log.ErrorF("command %v result error => %v", singleLineCommand, err)
}
//log.DebugF("real time exec result are %v", resultSlice)
return resultSlice
}
func realTimeOutput(r io.Reader) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
func collectOutput(r io.Reader, resultSlice []string) []string {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
resultLine := scanner.Text()
resultSlice = append(resultSlice, resultLine)
// debug usage
//fmt.Println(resultLine)
}
return resultSlice
}

View File

@@ -0,0 +1,13 @@
package executor
import "testing"
func TestReadTimeOutput(t *testing.T) {
strings := []string{
"/bin/bash",
"/root/IdeaProjects/ProjectOctopus/agent-go/tmp/simple.sh",
}
AllOutputCommandExecutor(strings)
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
systemctl stop firewalld
systemctl disable firewalld

View File

@@ -1 +0,0 @@
package g

View File

@@ -1,172 +0,0 @@
package g
import (
"bytes"
"fmt"
"github.com/nacos-group/nacos-sdk-go/v2/clients"
"github.com/nacos-group/nacos-sdk-go/v2/clients/config_client"
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
"github.com/nacos-group/nacos-sdk-go/v2/vo"
"github.com/spf13/viper"
"go.uber.org/zap"
"strconv"
"strings"
)
var log = G.LOG
var group = ""
func InitNacos(configFileName string) *viper.Viper {
v := parseAgentConfigFile(configFileName, nil)
group = v.GetString("spring.cloud.nacos.config.group")
// build the nacos connection
configClient := startNacosConnection(v)
// get all needed nacos config and merge
allNacosConfig := getAllNacosConfig(v, group, configClient)
for _, nacosConfigContent := range allNacosConfig {
log.Debug(fmt.Sprintf("nacos config conetent is %s", nacosConfigContent))
parseNacosConfigContend(nacosConfigContent, v)
}
log.Info(fmt.Sprintf("%s config read result are %v", configFileName, v.AllSettings()))
return v
}
func parseAgentConfigFile(configFileName string, v *viper.Viper) *viper.Viper {
// 使用Viper框架读取
if v == nil {
v = viper.New()
}
// 设置配置文件路径和名称
v.SetConfigName(configFileName)
v.AddConfigPath(".")
v.SetConfigType("yaml")
// 读取默认的总配置文件
err := v.ReadInConfig()
if err != nil {
panic(fmt.Errorf("fatal error config file: %s", err))
}
return v
}
func parseNacosConfigContend(configContent string, v *viper.Viper) *viper.Viper {
v.SetConfigType("yaml")
// use merge
err := v.MergeConfig(bytes.NewBuffer([]byte(configContent)))
if err != nil {
log.Error("nacos config contend read error !", zap.Error(err))
}
return v
}
func startNacosConnection(v *viper.Viper) config_client.IConfigClient {
serverAddr := v.GetString("spring.cloud.nacos.config.server-addr")
clientConfig := constant.ClientConfig{
//Endpoint: serverAddr,
NamespaceId: "",
TimeoutMs: v.GetUint64("spring.cloud.nacos.config.timeout"),
NotLoadCacheAtStart: true,
AppendToStdout: true,
UpdateCacheWhenEmpty: true,
//LogDir: "/tmp/nacos/log",
//CacheDir: "/tmp/nacos/cache",
Username: "nacos",
Password: "Superwmm.23",
}
split := strings.Split(serverAddr, ":")
if len(split) != 2 {
log.Error("nacos server addr error!")
}
port, _ := strconv.ParseUint(split[1], 10, 64)
serverConfigs := []constant.ServerConfig{
{
IpAddr: split[0],
Port: port,
GrpcPort: port + 1000,
},
}
// Another way of create config client for dynamic configuration (recommend)
configClient, err := clients.NewConfigClient(
vo.NacosClientParam{
ClientConfig: &clientConfig,
ServerConfigs: serverConfigs,
},
)
if err != nil {
panic(err)
}
return configClient
}
func getAllNacosConfig(v *viper.Viper, group string, configClient config_client.IConfigClient) []string {
result := make([]string, 0)
// main nacos configs
mainNacosConfigFileName := v.GetString("spring.application.name") + "-" + v.GetString("spring.profiles.active") + "." + v.GetString("spring.cloud.nacos.config.file-extension")
log.Debug(fmt.Sprintf("main nacos config file name is %s", mainNacosConfigFileName))
configContent := getConfig(mainNacosConfigFileName, group, configClient)
result = append(result, configContent)
// additional nacos config
additionalNacosConfig := v.Get("spring.cloud.nacos.config.extension-configs")
// 增加断言判定map的类型
m, ok := additionalNacosConfig.([]interface{})
if !ok {
fmt.Println("additionalNacosConfig is not a slice")
return nil
}
for _, addConfigMap := range m {
realMap, _ := addConfigMap.(map[string]interface{})
// 拿到配置的Key
dataId := realMap["data-id"].(string)
group := realMap["group"].(string)
// 查询
config := getConfig(dataId, group, configClient)
result = append(result, config)
}
return result
}
// getConfig 从Nacos中获取相应的
func getConfig(dataId string, group string, configClient config_client.IConfigClient) string {
log.Debug(fmt.Sprintf("nacos config get method dataID is %s, group is %s", dataId, group))
content, err := configClient.GetConfig(vo.ConfigParam{
DataId: dataId,
Group: group,
})
if err != nil {
log.Error("nacos config get error !", zap.Error(err))
}
log.Debug(fmt.Sprintf("dataId %s , group %s, nacos config content is %s", dataId, group, content))
return content
}

View File

@@ -1,16 +1,15 @@
package g package g
import ( import (
"agent-go/config" logger2 "agent-go/logger"
"github.com/panjf2000/ants/v2" "github.com/panjf2000/ants/v2"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
type Global struct { type Global struct {
LOG *Logger AgentHasRegister bool
NacosConfig *viper.Viper AgentConfig *viper.Viper
AgentServerInfo *config.AgentServerInfo P *ants.Pool
P *ants.Pool
} }
const ( const (
@@ -19,23 +18,22 @@ const (
ExecOmType = "EXECUTOR" ExecOmType = "EXECUTOR"
StatusOmType = "STATUS" StatusOmType = "STATUS"
InitOmType = "INIT" InitOmType = "INIT"
AgentOmType = "AGENT"
BaseFuncOssUrlPrefix = "https://b2.107421.xyz/"
) )
var logger, _ = NewLogger() var pool, _ = ants.NewPool(100, ants.WithNonblocking(false), ants.WithLogger(logger2.Log), ants.WithMaxBlockingTasks(30), ants.WithDisablePurge(true))
var pool, _ = ants.NewPool(100, ants.WithNonblocking(true), ants.WithLogger(logger))
var G = NewGlobal( var G = NewGlobal(
logger,
pool, pool,
) )
// NewGlobal NewGlobal构造函数返回一个新的Global实例其中包含指定的Logger。 // NewGlobal NewGlobal构造函数返回一个新的Global实例其中包含指定的Logger。
func NewGlobal(logger *Logger, pool *ants.Pool) *Global { func NewGlobal(pool *ants.Pool) *Global {
return &Global{ return &Global{
LOG: logger, AgentHasRegister: false,
NacosConfig: nil, AgentConfig: nil,
AgentServerInfo: nil, P: pool,
P: pool,
} }
} }

View File

@@ -5,10 +5,10 @@ go 1.18
require ( require (
github.com/nacos-group/nacos-sdk-go/v2 v2.2.0 github.com/nacos-group/nacos-sdk-go/v2 v2.2.0
github.com/panjf2000/ants/v2 v2.7.2 github.com/panjf2000/ants/v2 v2.7.2
github.com/shirou/gopsutil/v3 v3.23.3
github.com/spf13/viper v1.15.0 github.com/spf13/viper v1.15.0
github.com/streadway/amqp v1.0.0 github.com/streadway/amqp v1.0.0
go.uber.org/zap v1.24.0 go.uber.org/zap v1.24.0
gopkg.in/yaml.v3 v3.0.1
) )
require ( require (
@@ -17,11 +17,13 @@ require (
github.com/buger/jsonparser v1.1.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/golang/mock v1.6.0 // indirect github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect github.com/magiconair/properties v1.8.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
@@ -29,20 +31,25 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/client_golang v1.12.2 // indirect github.com/prometheus/client_golang v1.12.2 // indirect
github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/procfs v0.7.3 // indirect
github.com/shoenig/go-m1cpu v0.1.4 // indirect
github.com/spf13/afero v1.9.3 // indirect github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.4.2 // indirect github.com/subosito/gotenv v1.4.2 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.8.0 // indirect
golang.org/x/net v0.4.0 // indirect golang.org/x/net v0.4.0 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.3.0 // indirect golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.5.0 // indirect golang.org/x/text v0.5.0 // indirect
golang.org/x/time v0.1.0 // indirect golang.org/x/time v0.1.0 // indirect
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect
@@ -50,4 +57,5 @@ require (
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View File

@@ -93,6 +93,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
@@ -140,6 +142,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -189,6 +192,8 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
@@ -217,6 +222,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
@@ -242,6 +249,12 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE=
github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU=
github.com/shoenig/go-m1cpu v0.1.4 h1:SZPIgRM2sEF9NJy50mRHu9PKGwxyyTTJIWvCtgVbozs=
github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c=
github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
@@ -268,15 +281,22 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -410,6 +430,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -433,6 +454,7 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -445,8 +467,9 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@@ -1,4 +1,4 @@
package g package logger
import ( import (
"fmt" "fmt"
@@ -11,6 +11,8 @@ type Logger struct {
*zap.Logger *zap.Logger
} }
var Log, _ = NewLogger()
// NewLogger creates a new Logger instance. // NewLogger creates a new Logger instance.
func NewLogger() (*Logger, error) { func NewLogger() (*Logger, error) {
config := zap.Config{ config := zap.Config{
@@ -23,7 +25,7 @@ func NewLogger() (*Logger, error) {
LevelKey: "level", LevelKey: "level",
TimeKey: "time", TimeKey: "time",
//CallerKey: "caller", //CallerKey: "caller",
EncodeLevel: zapcore.CapitalColorLevelEncoder, EncodeLevel: zapcore.CapitalLevelEncoder,
EncodeTime: zapcore.RFC3339TimeEncoder, EncodeTime: zapcore.RFC3339TimeEncoder,
//EncodeCaller: zapcore.FullCallerEncoder, //EncodeCaller: zapcore.FullCallerEncoder,
}, },
@@ -65,8 +67,9 @@ func (l *Logger) Warn(msg string, fields ...zap.Field) {
} }
// Error logs an error message. // Error logs an error message.
func (l *Logger) Error(msg string, fields ...zap.Field) {
l.Logger.Error(msg, fields...) func (l *Logger) ErrorF(msg string, args ...interface{}) {
l.Logger.Error(fmt.Sprintf(msg, args...))
} }
// Fatal logs a fatal message and exits the program with a non-zero status code. // Fatal logs a fatal message and exits the program with a non-zero status code.

View File

@@ -2,12 +2,13 @@ package main
import ( import (
"agent-go/g" "agent-go/g"
logger2 "agent-go/logger"
"agent-go/register" "agent-go/register"
"flag" "flag"
"fmt" "fmt"
) )
var log = g.G.LOG var log = logger2.Log
func main() { func main() {
@@ -17,12 +18,12 @@ func main() {
flag.Parse() flag.Parse()
// 读取对应版本的配置文件 // 读取对应版本的配置文件
filename := fmt.Sprintf("octopus-agent-%s.yaml", version) filename := fmt.Sprintf("octopus-agent-%s.yaml", version)
println(filename) println("config file name is => " + filename)
// 初始化Nacos的连接配置 // 初始化Nacos的连接配置
g.G.NacosConfig = g.InitNacos(filename) g.G.AgentConfig = register.ParseConfiguration(filename)
// 执行初始化之策工作 // 执行初始化之策工作
g.G.AgentServerInfo = register.INIT() AgentServerInfoCache = INIT()
} }

View File

@@ -1,22 +1,91 @@
spring:
application:
name: octopus-agent
profiles:
active: dev
cloud:
nacos:
config:
group: dev
config-retry-time: 3000
file-extension: yaml
max-retry: 3
# server-addr: "150.230.198.103:21060"
server-addr: "42.192.52.227:21060"
timeout: 5000
config-long-poll-timeout: 5000
extension-configs:
- group: dev
data-id: "common-dev.yaml"
server: server:
port: 8000 port: 8000
logging:
level:
web: info
octopus:
message:
# agent boot up default common exchange
init_exchange: InitExchange
# server will send message to agent using this common queue
init_to_server: InitToServer
# agent boot up default common exchange routing key
init_to_server_key: InitToServerKey
# server will receive message from agent using this common queue
init_from_server: InitFromServer
# agent boot up default common exchange routing key
init_from_server_key: InitFromServerKey
# initialization register time out (unit ms) default is 5 min
init_ttl: "3000000"
# Octopus Exchange Name == server comunicate with agent
octopus_exchange: OctopusExchange
# Octopus Message To Server == all agent send info to server queue and topic
octopus_to_server: OctopusToServer
executor:
name: executor-functions
status:
name: octopus-agent
healthy:
type: cron
cron: 10 */1 * * * ? *
start-delay: 30
metric:
pinch: 20
agent:
executor:
# agent执行一条Command的最长超时时间
processMaxTimeOut: 60
status:
app:
- Nginx/nginx
- MySQL/mysql
- Xray/xray
- OctopusAgent/octopus-agent
- Redis/redis
- RabbitMQ/rabbitmq
spring:
main:
allow-circular-references: true
allow-bean-definition-overriding: true
rabbitmq:
# host: 42.192.52.227
host: 192.168.35.71
port: 20672
username: boge
password: boge8tingH
virtual-host: /
listener:
simple:
retry:
# ack failed will reentrant the Rabbit Listener
max-attempts: 2
enabled: true
# retry interval unit ms
max-interval: 65000
initial-interval: 65000
#spring:
# application:
# name: octopus-agent
# profiles:
# active: dev
# cloud:
# nacos:
# config:
# group: dev
# config-retry-time: 3000
# file-extension: yaml
# max-retry: 3
# # server-addr: "150.230.198.103:21060"
# server-addr: "42.192.52.227:21060"
# timeout: 5000
# config-long-poll-timeout: 5000
# extension-configs:
# - group: dev
# data-id: "common-dev.yaml"
#
#server:
# port: 8000

View File

@@ -1,63 +0,0 @@
package rabbitmq
import (
"fmt"
"github.com/nacos-group/nacos-sdk-go/v2/common/logger"
"github.com/streadway/amqp"
)
// RabbitMQConn is a struct that holds the connection and channel objects
type RabbitMQConn struct {
Connection *amqp.Connection
Channel *amqp.Channel
}
type ConnectProperty struct {
ExchangeName string
QueueName string
ExchangeType string
TopicKey string
}
// Send 向RabbitMQ中发送消息
func Send(conn *RabbitMQConn, connProp *ConnectProperty, message []byte) {
// 往哪里发
channel := conn.Channel
// 发送
err := channel.Publish(
connProp.ExchangeName,
connProp.TopicKey,
false,
false,
amqp.Publishing{
ContentType: "text/plain",
Body: message,
},
)
if err != nil {
logger.Error(fmt.Sprintf("Failed to publish a message: %v", err))
}
}
func Read(conn *RabbitMQConn, connProp *ConnectProperty, autoAck bool) <-chan amqp.Delivery {
// 拿到特定的Channel
channel := conn.Channel
// 开始读取队列中的全部消息
msgs, err := channel.Consume(
connProp.QueueName, // 队列名称
"", // 消费者名称
autoAck, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // arguments
)
if err != nil {
log.Error(fmt.Sprintf("Failed to register a consumer: %v", err))
}
return msgs
}

View File

@@ -0,0 +1,78 @@
package rabbitmq
import (
"agent-go/g"
"encoding/json"
"fmt"
)
var OctopusToServerQueue = &RabbitQueue{}
var P = g.G.P
func BuildOMsgRuntimeConnectorQueue(agentTopicName string) {
// 建立 业务消息 接收队列
// agentTopicName为名称的队列
agentConfig := g.G.AgentConfig
octopusExchangeName := agentConfig.GetString("octopus.message.octopus_exchange")
octopusConnectProp := &ConnectProperty{
ExchangeName: octopusExchangeName,
QueueName: agentTopicName,
ExchangeType: g.QueueTopic,
TopicKey: agentTopicName + "*",
}
octopusMsgQueue := &RabbitQueue{
RabbitProp: octopusConnectProp,
}
octopusMsgQueue.Connect()
// 建立 业务消息 返回队列
// 统一为 OctopusToServer
octopusToServerQueueName := agentConfig.GetString("octopus.message.octopus_to_server")
octopusToServerProp := &ConnectProperty{
ExchangeName: octopusExchangeName,
QueueName: octopusToServerQueueName,
ExchangeType: g.QueueTopic,
TopicKey: octopusToServerQueueName,
}
OctopusToServerQueue = &RabbitQueue{
RabbitProp: octopusToServerProp,
}
// 开启运行时消息返回队列
OctopusToServerQueue.Connect()
log.InfoF("Octopus Message Business Runtime Queue is established ! => %v", OctopusToServerQueue)
deliveries := octopusMsgQueue.Read(true)
forever := make(chan bool)
P.Submit(
func() {
// 死循环处理Octopus Message
for delivery := range deliveries {
var om *OctopusMessage
err := json.Unmarshal(delivery.Body, &om)
if err != nil {
log.Error(fmt.Sprintf("octopus message convert to json is wrong! msg is => %s", delivery.Body))
// 保存到某处
continue
}
// 策略模式 处理消息
P.Submit(func() {
om.Handle()
})
}
})
// wait forever
<-forever
}

View File

@@ -0,0 +1,186 @@
package rabbitmq
import (
"agent-go/executor"
"agent-go/g"
"agent-go/status"
"agent-go/utils"
"encoding/json"
"fmt"
"strings"
)
type IOctopusMessage interface {
OctopusMsgHandler
OctopusMsgSender
OctopusMsgBuilder
}
type OctopusMsgHandler interface {
Handle(octopusMessage *OctopusMessage)
}
type OctopusMsgSender interface {
Send(rabbitQueue *RabbitQueue, msg []byte)
SendToOctopusServer()
}
type OctopusMsgBuilder interface {
Build(omType string, content interface{}) *OctopusMessage
}
type OctopusMessage struct {
UUID string `json:"uuid"`
InitTime string `json:"init_time" format:"2023-03-21 16:38:30"`
Type string `json:"type"`
Content interface{} `json:"content"`
Result interface{} `json:"result"`
ResultCode string `json:"resultCode"`
ACTime string `json:"ac_time" format:"2023-03-21 16:38:30"`
}
func (om *OctopusMessage) Handle() {
// 实际执行 OM handle进程
doHandleOctopusMessage(om)
}
func (om *OctopusMessage) Send(rabbitQueue *RabbitQueue, msg []byte) {
rabbitQueue.Send(msg)
}
// SendToOctopusServer send octopus message back to octopusToServer queue
func (om *OctopusMessage) SendToOctopusServer() {
// write the octopus message to bytes
octopusMessageReplayBytes, err := json.Marshal(om)
if err != nil {
log.ErrorF("replay octopus message write error => %v", err)
}
// Send back the result to queue
OctopusToServerQueue.Send(octopusMessageReplayBytes)
}
func (om *OctopusMessage) Build(omType string, content interface{}) *OctopusMessage {
// 当前时间
curTimeString := utils.ParseDateTimeTime()
// must write to string format, otherwise it's very hard to deserialize
bytes, err := json.Marshal(content)
if err != nil {
fmt.Sprintf("OctopusMessage Build Error ! %v", err)
}
return &OctopusMessage{
UUID: curTimeString,
InitTime: curTimeString,
Type: omType,
Content: string(bytes),
Result: nil,
ACTime: curTimeString,
}
}
func doHandleOctopusMessage(octopusMessage *OctopusMessage) {
switch octopusMessage.Type {
case g.InitOmType:
go func() {}()
case g.ExecOmType:
P.Submit(func() {
executorOMHandler(octopusMessage)
})
case g.StatusOmType:
P.Submit(func() {
statusOMHandler(octopusMessage)
})
case g.AgentOmType:
P.Submit(func() {
agentOMHandler(octopusMessage)
},
)
default:
P.Submit(func() {
blackHoleOMHandler(octopusMessage)
})
}
}
// agentOMHandler 处理Agent的核心操作指令
func agentOMHandler(octopusMessage *OctopusMessage) {
}
func executorOMHandler(octopusMessage *OctopusMessage) {
executionMsgString := octopusMessage.Content.(string)
var executionMessage *executor.ExecutionMessage
err := json.Unmarshal([]byte(executionMsgString), &executionMessage)
if err != nil {
log.Error(fmt.Sprintf("execution message convert to json is wrong! msg is => %s", executionMsgString))
return
}
// 交给后端的实际处理器处理, 再次策略
resultLog, err := executor.Execute(executionMessage)
if err != nil {
octopusMessage.ResultCode = "200"
} else {
octopusMessage.ResultCode = "300"
}
// send back the result log
octopusMessage.Result = resultLog
octopusMessage.ACTime = utils.ParseISOLocalDateTime()
// Send
octopusMessage.SendToOctopusServer()
}
func statusOMHandler(octopusMessage *OctopusMessage) {
v, ok := (octopusMessage.Content).(string)
if !ok {
log.ErrorF("convert to string is wrong %s", v)
}
statusMsgString := octopusMessage.Content.(string)
var statusMessage *status.StatusMessage
err := json.Unmarshal([]byte(statusMsgString), &statusMessage)
if err != nil {
fmt.Println(err.Error())
log.Error(fmt.Sprintf("status message convert to json is wrong! msg is => %s", octopusMessage))
return
}
var statusRes string
if strings.HasPrefix(statusMessage.StatusType, "P") {
// ping info
statusRes = status.Ping()
} else {
// status info
agentStatusString, _ := json.Marshal(status.ReportAppStatus())
statusRes = string(agentStatusString)
}
// 返回消息
// 组装消息
octopusMessage.ACTime = utils.ParseDateTimeTime()
octopusMessage.Result = statusRes
// 发送回去
statusOctopusReplayMessage, _ := json.Marshal(octopusMessage)
OctopusToServerQueue.Send(statusOctopusReplayMessage)
// 输出日志
log.InfoF("接收到查询Agent状态的请求结果为 => %s", statusRes)
}
func blackHoleOMHandler(octopusMessage *OctopusMessage) {
log.Error(fmt.Sprintf("[BLACK HOLE] octopusMessage type wrong! msg is => %v", octopusMessage))
}

View File

@@ -1,106 +0,0 @@
package rabbitmq
import (
"agent-go/config"
"agent-go/executor"
"agent-go/g"
"encoding/json"
"fmt"
)
var P = g.G.P
func HandleOMsg(initOMsgFromServer *config.OctopusMessage) {
agentTopicName := initOMsgFromServer.Result.(string)
OctopusExchange := g.G.NacosConfig.GetString("octopus.message.octopus_exchange")
octopusConnectProp := &ConnectProperty{
ExchangeName: OctopusExchange,
QueueName: agentTopicName,
ExchangeType: g.QueueTopic,
TopicKey: agentTopicName + "*",
}
octopusConn, err := NewRabbitMQConn(octopusConnectProp)
if err != nil {
log.Error(fmt.Sprintf("Octopus Message Queue create Error ! => %v", octopusConnectProp))
panic(err)
}
// 开始接收消息
channel := octopusConn.Channel
deliveries, err := channel.Consume(
agentTopicName,
agentTopicName,
true,
false,
false,
false,
nil,
)
if err != nil {
return
}
// 死循环处理Ocotpus Message
for delivery := range deliveries {
var om *config.OctopusMessage
err := json.Unmarshal(delivery.Body, &om)
if err != nil {
log.Error(fmt.Sprintf("octopus message convert to json is wrong! msg is => %s", delivery.Body))
// 保存到某处
continue
}
// 策略模式 处理消息
doHandleOctopusMessage(om)
}
}
func doHandleOctopusMessage(octopusMessage *config.OctopusMessage) {
switch octopusMessage.Type {
case g.InitOmType:
go func() {}()
case g.ExecOmType:
P.Submit(func() {
executorOMHandler(octopusMessage)
})
case g.StatusOmType:
P.Submit(func() {
statusOMHandler(octopusMessage)
})
default:
P.Submit(func() {
blackHoleOMHandler(octopusMessage)
})
}
}
func executorOMHandler(octopusMessage *config.OctopusMessage) {
executionMsgString := octopusMessage.Content.(string)
var executionMessage *config.ExecutionMessage
err := json.Unmarshal([]byte(executionMsgString), &executionMessage)
if err != nil {
log.Error(fmt.Sprintf("execution message convert to json is wrong! msg is => %s", executionMsgString))
return
}
// 交给后端的实际处理器处理, 再次策略
executor.Execute(octopusMessage, executionMessage)
}
func statusOMHandler(octopusMessage *config.OctopusMessage) {
}
func blackHoleOMHandler(octopusMessage *config.OctopusMessage) {
log.Error(fmt.Sprintf("octopusMessage type wrong! msg is => %v", octopusMessage))
}

View File

@@ -1,154 +0,0 @@
package rabbitmq
import (
"agent-go/g"
"fmt"
"github.com/streadway/amqp"
"strings"
"sync"
)
var log = g.G.LOG
// 定义全局唯一的 Singleton 实例
var instance *amqp.Connection
// 用 sync.Once 变量确保初始化函数只会被调用一次
var once sync.Once
// 初始化 Singleton 实例的函数
func createInstance() {
// 在这里进行 Singleton 的初始化操作
// 获取RabbitMQ的连接地址
rabbitMQEndpointFromG := parseRabbitMQEndpointFromG()
// 创建全局唯一连接 RabbitMQ连接
connection, err := amqp.Dial(rabbitMQEndpointFromG)
if err != nil {
log.Error(fmt.Sprintf("failed to connect to RabbitMQ: %v", err))
}
instance = connection
}
// GetInstance 获取全局唯一的 Singleton 实例的函数
func GetInstance() *amqp.Connection {
// 使用 sync.Once 确保 createInstance 只会被调用一次
once.Do(createInstance)
return instance
}
// NewRabbitMQConn creates a new RabbitMQ connection object
func NewRabbitMQConn(property *ConnectProperty) (*RabbitMQConn, error) {
// 获取RabbitMQ的连接
conn := GetInstance()
// 获取RabbitMQ的连接地址
//rabbitMQEndpointFromG := parseRabbitMQEndpointFromG()
//conn, err := amqp.Dial(rabbitMQEndpointFromG)
//if err != nil {
// log.Error(fmt.Sprintf("failed to connect to RabbitMQ: %v", err))
//}
ch, err := conn.Channel()
if err != nil {
return nil, fmt.Errorf("failed to create RabbitMQ channel: %w", err)
}
if err = ch.ExchangeDeclare(
property.ExchangeName, // name of the exchange
property.ExchangeType, // type of the exchange
false, // durable
false, // delete when complete
false, // internal
false, // noWait
nil, // arguments
); err != nil {
return nil, fmt.Errorf("failed to declare RabbitMQ exchange: %w", err)
}
_, err = ch.QueueDeclare(
property.QueueName, // name of the queue
false, // durable
false, // delete when unused
false, // exclusive
false, // noWait
nil, // arguments
)
if err != nil {
return nil, fmt.Errorf("failed to declare RabbitMQ queue: %w", err)
}
if err = ch.QueueBind(
property.QueueName, // name of the queue
property.TopicKey, // routing key - all topics
property.ExchangeName, // name of the exchange
false, // noWait
nil, // arguments
); err != nil {
return nil, fmt.Errorf("failed to bind RabbitMQ queue: %w", err)
}
return &RabbitMQConn{Connection: conn, Channel: ch}, nil
}
// parseRabbitMQEndpoint 根据全局变量NacosConfig解析出RabbitMQ的连接地址
func parseRabbitMQEndpointFromG() string {
nacosConfig := g.G.NacosConfig
var res strings.Builder
host := nacosConfig.GetString("spring.rabbitmq.host")
port := nacosConfig.GetString("spring.rabbitmq.port")
username := nacosConfig.GetString("spring.rabbitmq.username")
password := nacosConfig.GetString("spring.rabbitmq.password")
virtualHost := nacosConfig.GetString("spring.rabbitmq.virtual-host")
// amqp://{username}:{password}@{hostname}:{port}/{virtual_host}
res.WriteString("amqp://")
res.WriteString(username)
res.WriteString(":")
res.WriteString(password)
res.WriteString("@")
res.WriteString(host)
res.WriteString(":")
res.WriteString(port)
res.WriteString("/")
res.WriteString(virtualHost)
s := res.String()
log.Debug(fmt.Sprintf("generate RabbitMQ endpoint is %s", s))
return s
}
func CloseChannel(conn *RabbitMQConn) error {
var err error
if conn.Channel != nil {
if err = conn.Channel.Close(); err != nil {
log.Error(fmt.Sprintf("Failed to close RabbitMQ channel: %v", err))
}
}
return err
}
// CloseRabbitMQAll closes the RabbitMQ connection and channel
func (r *RabbitMQConn) CloseRabbitMQAll() error {
var err error
if r.Channel != nil {
if err = r.Channel.Close(); err != nil {
log.Error(fmt.Sprintf("Failed to close RabbitMQ channel: %v", err))
}
}
if r.Connection != nil {
if err = r.Connection.Close(); err != nil {
log.Error(fmt.Sprintf("Failed to close RabbitMQ connection: %v", err))
}
}
return err
}

View File

@@ -0,0 +1,214 @@
package rabbitmq
import (
"agent-go/g"
logger2 "agent-go/logger"
"fmt"
"github.com/streadway/amqp"
"strings"
"sync"
)
type RabbitMQ interface {
RabbitSendWriter
RabbitConnectCloser
}
type RabbitSendWriter interface {
Send(message []byte)
Read(autoAck bool) <-chan amqp.Delivery
}
type RabbitConnectCloser interface {
Connect()
Close() error
}
type RabbitQueue struct {
RabbitConn *RabbitMQConn
RabbitProp *ConnectProperty
}
// RabbitMQConn is a struct that holds the connection and channel objects
type RabbitMQConn struct {
Connection *amqp.Connection
Channel *amqp.Channel
}
type ConnectProperty struct {
ExchangeName string
QueueName string
ExchangeType string
TopicKey string
}
var log = logger2.Log
// 定义全局唯一的 Singleton 实例
var instance *amqp.Connection
// 用 sync.Once 变量确保初始化函数只会被调用一次
var once sync.Once
// 初始化 Singleton 实例的函数
func createInstance() {
// 在这里进行 Singleton 的初始化操作
// 获取RabbitMQ的连接地址
rabbitMQEndpointFromG := parseRabbitMQEndpointFromG()
// 创建全局唯一连接 RabbitMQ连接
connection, err := amqp.Dial(rabbitMQEndpointFromG)
if err != nil {
log.Error(fmt.Sprintf("failed to connect to RabbitMQ: %v", err))
}
instance = connection
}
// GetInstance 获取全局唯一的 Singleton 实例的函数
func GetInstance() *amqp.Connection {
// 使用 sync.Once 确保 createInstance 只会被调用一次
once.Do(createInstance)
return instance
}
// Connect creates a new RabbitMQ connection object
func (r *RabbitQueue) Connect() {
// 获取RabbitMQ的连接
conn := GetInstance()
ch, err := conn.Channel()
if err != nil {
log.Error(fmt.Sprintf("failed to create RabbitMQ channel: %w", err))
}
if err = ch.ExchangeDeclare(
r.RabbitProp.ExchangeName, // name of the exchange
r.RabbitProp.ExchangeType, // type of the exchange
true, // durable
false, // delete when complete
false, // internal
false, // noWait
nil, // arguments
); err != nil {
log.Error(fmt.Sprintf("failed to declare exchange !: %w", err))
}
_, err = ch.QueueDeclare(
r.RabbitProp.QueueName, // name of the queue
true, // durable
false, // delete when unused
false, // exclusive
false, // noWait
nil, // arguments
)
if err != nil {
log.Error(fmt.Sprintf("failed to declare RabbitMQ queue: %w", err))
}
if err = ch.QueueBind(
r.RabbitProp.QueueName, // name of the queue
r.RabbitProp.TopicKey, // routing key - all topics
r.RabbitProp.ExchangeName, // name of the exchange
false, // noWait
nil, // arguments
); err != nil {
log.Error(fmt.Sprintf("failed to bind RabbitMQ queue: %w", err))
}
r.RabbitConn = &RabbitMQConn{
Connection: conn,
Channel: ch,
}
}
func (r *RabbitQueue) Close() error {
var err error
if r.RabbitConn.Channel != nil {
if err = r.RabbitConn.Channel.Close(); err != nil {
log.Error(fmt.Sprintf("Failed to close RabbitMQ channel: %v", err))
}
}
return err
}
// Send 向RabbitMQ中发送消息
func (r *RabbitQueue) Send(message []byte) {
// 往哪里发
channel := r.RabbitConn.Channel
// 发送
err := channel.Publish(
r.RabbitProp.ExchangeName,
r.RabbitProp.TopicKey,
false,
false,
amqp.Publishing{
ContentType: "text/plain",
Body: message,
},
)
if err != nil {
log.Error(fmt.Sprintf("Failed to publish a message: %v", err))
}
}
func (r *RabbitQueue) Read(autoAck bool) <-chan amqp.Delivery {
// 拿到特定的Channel
channel := r.RabbitConn.Channel
// 开始读取队列中的全部消息
msgs, err := channel.Consume(
r.RabbitProp.QueueName, // 队列名称
"", // 消费者名称
autoAck, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // arguments
)
if err != nil {
log.Error(fmt.Sprintf("Failed to register a consumer: %v", err))
}
return msgs
}
// parseRabbitMQEndpoint 根据全局变量agentConfig解析出RabbitMQ的连接地址
func parseRabbitMQEndpointFromG() string {
agentConfig := g.G.AgentConfig
var res strings.Builder
host := agentConfig.GetString("spring.rabbitmq.host")
port := agentConfig.GetString("spring.rabbitmq.port")
username := agentConfig.GetString("spring.rabbitmq.username")
password := agentConfig.GetString("spring.rabbitmq.password")
virtualHost := agentConfig.GetString("spring.rabbitmq.virtual-host")
// amqp://{username}:{password}@{hostname}:{port}/{virtual_host}
res.WriteString("amqp://")
res.WriteString(username)
res.WriteString(":")
res.WriteString(password)
res.WriteString("@")
res.WriteString(host)
res.WriteString(":")
res.WriteString(port)
res.WriteString("/")
res.WriteString(virtualHost)
s := res.String()
log.Debug(fmt.Sprintf("generate RabbitMQ endpoint is %s", s))
return s
}

View File

@@ -1,173 +0,0 @@
package register
import (
"agent-go/config"
"agent-go/g"
"agent-go/rabbitmq"
"encoding/json"
"fmt"
"gopkg.in/yaml.v3"
"io/ioutil"
)
var omType = g.InitOmType
var log = g.G.LOG
func INIT() *config.AgentServerInfo {
// 获取系统的环境变量
agentServerInfo := parseAgentServerInfo()
nacosConfig := g.G.NacosConfig
initToServerProp := &rabbitmq.ConnectProperty{
ExchangeName: nacosConfig.GetString("octopus.message.init_exchange"),
QueueName: nacosConfig.GetString("octopus.message.init_to_server"),
ExchangeType: g.QueueDirect,
TopicKey: nacosConfig.GetString("octopus.message.init_to_server_key"),
}
initFromServerProp := &rabbitmq.ConnectProperty{
ExchangeName: nacosConfig.GetString("octopus.message.init_exchange"),
QueueName: nacosConfig.GetString("octopus.message.init_from_server"),
ExchangeType: g.QueueDirect,
TopicKey: nacosConfig.GetString("octopus.message.init_from_server_key"),
}
// 建立RabbitMQ的连接
// defer 关闭初始化连接
initToServer, err := rabbitmq.NewRabbitMQConn(
initToServerProp,
)
if err != nil {
log.Error("init to server queue established error!")
panic(err)
}
//defer rabbitmq.CloseChannel(initToServer)
//defer rabbitmq.CloseChannel(initFromServer)
// 组装OctopusMessage
var octopusMsg *config.OctopusMessage
octopusMsg = octopusMsg.BuildOctopusMsg(
omType,
agentServerInfo,
)
msgBytes, err := json.Marshal(octopusMsg)
if err != nil {
log.Error(fmt.Sprintf("octopus message convert to json is wrong! msg is => %v", octopusMsg))
}
log.Debug(fmt.Sprintf("Prepare to send init message to server! ==> %s", string(msgBytes)))
// 发送OM至MQ中
rabbitmq.Send(
initToServer,
initToServerProp,
msgBytes,
)
// 监听初始化连接中的信息
initFromServer, err := rabbitmq.NewRabbitMQConn(
initFromServerProp,
)
if err != nil {
log.Error("init from server queue established error!")
panic(err)
}
// 建立运行时RabbitMQ连接
handleInitMsgFromServer(initFromServer, initFromServerProp, initToServer, initToServerProp, agentServerInfo)
return agentServerInfo
}
// handleInitMsgFromServer 处理从Server接收的注册信息
func handleInitMsgFromServer(initFromServer *rabbitmq.RabbitMQConn, initFromServerProp *rabbitmq.ConnectProperty, initToServer *rabbitmq.RabbitMQConn, initToServerProp *rabbitmq.ConnectProperty, agentServerInfo *config.AgentServerInfo) {
deliveries := rabbitmq.Read(initFromServer, initFromServerProp, false)
forever := make(chan bool)
go func() {
// 同步很多抢占注册的情况
for delivery := range deliveries {
log.Debug(fmt.Sprintf("message received from server is %s", string(delivery.Body)))
var om *config.OctopusMessage
err := json.Unmarshal(delivery.Body, &om)
if err != nil {
log.Error(fmt.Sprintf("parse init message from server wroong, message is => %s ",
string(delivery.Body)))
}
var serverInfo config.AgentServerInfo
s, _ := om.Content.(string)
cc := json.Unmarshal([]byte(s), &serverInfo)
if cc != nil {
log.Error(fmt.Sprintf("parse init message from server wroong, message is => %v ", cc))
}
serverName := serverInfo.ServerName
// 处理OM信息
if om != nil && om.Type == g.InitOmType && serverName == agentServerInfo.ServerName {
// 是本机的注册回复信息
// 建立运行时RabbitMQ连接
// change to async
go rabbitmq.HandleOMsg(om)
// 手动确认信息
delivery.Ack(false)
// 手动关闭 注册队列的连接
shutdownRegisterQueueConnection(initFromServer, initFromServerProp, initToServer, initToServerProp)
return
}
// 不是自身的 注册回复信息 -- 拒绝
log.Warn(fmt.Sprintf("OctopusMessage INIT from server not this agent ! => %v, ==>%s", om, delivery.Body))
delivery.Nack(false, true)
}
}()
// wait forever
<-forever
}
// shutdownRegisterQueueConnection 关闭初始化连接的两个队列
func shutdownRegisterQueueConnection(initFromServer *rabbitmq.RabbitMQConn, initFromServerProp *rabbitmq.ConnectProperty, initToServer *rabbitmq.RabbitMQConn, initToServerProp *rabbitmq.ConnectProperty) {
}
func parseAgentServerInfo() *config.AgentServerInfo {
// 约定文件地址为 /etc/environment.d/octopus-agent.conf
// 目前使用
var agentServerInfo *config.AgentServerInfo
yamlFile, err := ioutil.ReadFile("C:\\Users\\wdd\\IdeaProjects\\ProjectOctopus\\agent-go\\server-env.yaml")
if err != nil {
panic(fmt.Errorf("failed to read YAML file: %v", err))
}
err = yaml.Unmarshal(yamlFile, &agentServerInfo)
if err != nil {
panic(fmt.Errorf("failed to unmarshal YAML: %v", err))
}
jsonFormat, err := json.Marshal(agentServerInfo)
if err != nil {
log.Error(fmt.Sprintf("agent server info convert error ! agentserverinfo is %v", agentServerInfo))
panic(err)
}
log.Info(fmt.Sprintf("agent server info is %v", string(jsonFormat)))
return agentServerInfo
}

View File

@@ -1,4 +1,4 @@
package config package register
type AgentServerInfo struct { type AgentServerInfo struct {
ServerName string `json:"serverName" yaml:"serverName"` ServerName string `json:"serverName" yaml:"serverName"`
@@ -22,5 +22,5 @@ type AgentServerInfo struct {
Comment string `json:"comment" yaml:"comment"` Comment string `json:"comment" yaml:"comment"`
MachineID string `json:"machineId" yaml:"machineId"` MachineID string `json:"machineId" yaml:"machineId"`
AgentVersion string `json:"agentVersion" yaml:"agentVersion"` AgentVersion string `json:"agentVersion" yaml:"agentVersion"`
AgentTopicName string `json:"agentTopicName" yaml:"agentTopicName"` TopicName string `json:"topicName" yaml:"topicName"`
} }

View File

@@ -0,0 +1,34 @@
package register
import (
"fmt"
"github.com/spf13/viper"
)
func ParseConfiguration(configFileName string) *viper.Viper {
agentConfig := parseAgentConfigFile(configFileName, nil)
return agentConfig
}
func parseAgentConfigFile(configFileName string, v *viper.Viper) *viper.Viper {
// 使用Viper框架读取
if v == nil {
v = viper.New()
}
// 设置配置文件路径和名称
v.SetConfigName(configFileName)
v.AddConfigPath(".")
v.SetConfigType("yaml")
// 读取默认的总配置文件
err := v.ReadInConfig()
if err != nil {
panic(fmt.Errorf("fatal error config file: %s", err))
}
return v
}

View File

@@ -0,0 +1,172 @@
package register
//
//import (
// "bytes"
// "fmt"
// "github.com/nacos-group/nacos-sdk-go/v2/clients"
// "github.com/nacos-group/nacos-sdk-go/v2/clients/config_client"
// "github.com/nacos-group/nacos-sdk-go/v2/common/constant"
// "github.com/nacos-group/nacos-sdk-go/v2/vo"
// "github.com/spf13/viper"
// "go.uber.org/zap"
// "strconv"
// "strings"
//)
//
//var group = ""
//
//func InitNacos(configFileName string) *viper.Viper {
//
// v := parseAgentConfigFile(configFileName, nil)
// group = v.GetString("spring.cloud.nacos.config.group")
//
// // build the nacos connection
// configClient := startNacosConnection(v)
//
// // get all needed nacos config and merge
// allNacosConfig := getAllNacosConfig(v, group, configClient)
//
// for _, nacosConfigContent := range allNacosConfig {
// log.Debug(fmt.Sprintf("nacos config conetent is %s", nacosConfigContent))
//
// parseNacosConfigContend(nacosConfigContent, v)
// }
//
// log.Info(fmt.Sprintf("%s config read result are %v", configFileName, v.AllSettings()))
//
// return v
//}
//
//func parseAgentConfigFile(configFileName string, v *viper.Viper) *viper.Viper {
//
// // 使用Viper框架读取
// if v == nil {
// v = viper.New()
// }
//
// // 设置配置文件路径和名称
// v.SetConfigName(configFileName)
// v.AddConfigPath(".")
// v.SetConfigType("yaml")
//
// // 读取默认的总配置文件
// err := v.ReadInConfig()
// if err != nil {
// panic(fmt.Errorf("fatal error config file: %s", err))
// }
//
// return v
//}
//
//func parseNacosConfigContend(configContent string, v *viper.Viper) *viper.Viper {
//
// v.SetConfigType("yaml")
//
// // use merge
//
// err := v.MergeConfig(bytes.NewBuffer([]byte(configContent)))
// if err != nil {
// log.Error("nacos config contend read error !", zap.Error(err))
// }
//
// return v
//}
//func startNacosConnection(v *viper.Viper) config_client.IConfigClient {
//
// serverAddr := v.GetString("spring.cloud.nacos.config.server-addr")
//
// clientConfig := constant.ClientConfig{
// //Endpoint: serverAddr,
// NamespaceId: "",
// TimeoutMs: v.GetUint64("spring.cloud.nacos.config.timeout"),
// NotLoadCacheAtStart: true,
// AppendToStdout: true,
// UpdateCacheWhenEmpty: true,
// //LogDir: "/tmp/nacos/log",
// //CacheDir: "/tmp/nacos/cache",
// Username: "nacos",
// Password: "Superwmm.23",
// }
//
// split := strings.Split(serverAddr, ":")
// if len(split) != 2 {
// log.Error("nacos server addr error!")
// }
//
// port, _ := strconv.ParseUint(split[1], 10, 64)
// serverConfigs := []constant.ServerConfig{
// {
// IpAddr: split[0],
// Port: port,
// GrpcPort: port + 1000,
// },
// }
//
// // Another way of create config client for dynamic configuration (recommend)
// configClient, err := clients.NewConfigClient(
// vo.NacosClientParam{
// ClientConfig: &clientConfig,
// ServerConfigs: serverConfigs,
// },
// )
// if err != nil {
// panic(err)
// }
//
// return configClient
//}
//
//func getAllNacosConfig(v *viper.Viper, group string, configClient config_client.IConfigClient) []string {
//
// result := make([]string, 0)
//
// // main nacos configs
// mainNacosConfigFileName := v.GetString("spring.application.name") + "-" + v.GetString("spring.profiles.active") + "." + v.GetString("spring.cloud.nacos.config.file-extension")
//
// log.Debug(fmt.Sprintf("main nacos config file name is %s", mainNacosConfigFileName))
// configContent := getConfig(mainNacosConfigFileName, group, configClient)
// result = append(result, configContent)
//
// // additional nacos config
// additionalNacosConfig := v.Get("spring.cloud.nacos.config.extension-configs")
// // 增加断言判定map的类型
// m, ok := additionalNacosConfig.([]interface{})
// if !ok {
// fmt.Println("additionalNacosConfig is not a slice")
// return nil
// }
//
// for _, addConfigMap := range m {
//
// realMap, _ := addConfigMap.(map[string]interface{})
//
// // 拿到配置的Key
// dataId := realMap["data-id"].(string)
// group := realMap["group"].(string)
//
// // 查询
// config := getConfig(dataId, group, configClient)
// result = append(result, config)
// }
//
// return result
//}
//
//// getConfig 从Nacos中获取相应的
//func getConfig(dataId string, group string, configClient config_client.IConfigClient) string {
//
// log.Debug(fmt.Sprintf("nacos config get method dataID is %s, group is %s", dataId, group))
//
// content, err := configClient.GetConfig(vo.ConfigParam{
// DataId: dataId,
// Group: group,
// })
// if err != nil {
// log.Error("nacos config get error !", zap.Error(err))
// }
//
// log.Debug(fmt.Sprintf("dataId %s , group %s, nacos config content is %s", dataId, group, content))
//
// return content
//}

View File

@@ -1,4 +1,4 @@
serverName: "Chengdu-amd64-98" serverName: "Chengdu-amd64-90"
serverIpPbV4: "183.220.149.17" serverIpPbV4: "183.220.149.17"
serverIpInV4: "" serverIpInV4: ""
serverIpPbV6: "" serverIpPbV6: ""
@@ -17,6 +17,6 @@ osKernelInfo: "5.4.0-135-generic"
tcpControl: "cubic" tcpControl: "cubic"
virtualization: "Dedicated" virtualization: "Dedicated"
ioSpeed: "150 MB/s" ioSpeed: "150 MB/s"
machineId: "" machineId: "fakemachinid123"
agentVersion: "" agentVersion: ""
agentTopicName: "" topicName: ""

50
agent-go/status/CPU.go Normal file
View File

@@ -0,0 +1,50 @@
package status
import (
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/load"
)
type CPUStatus struct {
NumCores int
CPUInfo []cpu.InfoStat
CPUPercent float64
CPULoads *load.AvgStat
SystemLoads *load.AvgStat
}
func GetCPUStatus() (*CPUStatus, error) {
numCores, err := cpu.Counts(true)
if err != nil {
return nil, err
}
cpuInfo, err := cpu.Info()
if err != nil {
return nil, err
}
cpuPercent, err := cpu.Percent(0, false)
if err != nil {
return nil, err
}
cpuLoads, err := load.Avg()
if err != nil {
return nil, err
}
systemLoads, err := load.Avg()
if err != nil {
return nil, err
}
return &CPUStatus{
NumCores: numCores,
CPUInfo: cpuInfo,
CPUPercent: cpuPercent[0],
CPULoads: cpuLoads,
SystemLoads: systemLoads,
}, nil
}

View File

@@ -0,0 +1,22 @@
package status
import (
"encoding/json"
"fmt"
"testing"
)
func TestGetCPUStatus(t *testing.T) {
cpuStatus, err := GetCPUStatus()
if err != nil {
return
}
marshalIndent, err := json.MarshalIndent(cpuStatus, "", " ")
if err != nil {
fmt.Printf("error")
}
fmt.Println(string(marshalIndent))
}

48
agent-go/status/Disk.go Normal file
View File

@@ -0,0 +1,48 @@
package status
import (
"fmt"
"github.com/shirou/gopsutil/v3/disk"
"runtime"
"time"
)
type DiskStatus struct {
Total uint64
Used uint64
LogicalDisk []disk.PartitionStat
}
func GetDiskStatus() *DiskStatus {
ds := &DiskStatus{}
// Get disk usage
du, _ := disk.Usage("/")
ds.Total = du.Total
ds.Used = du.Used
// Get logical disk info for Linux systems
if runtime.GOOS == "linux" {
ld, _ := disk.Partitions(true)
ds.LogicalDisk = ld
}
return ds
}
func CalculateDiskIO() {
// Get initial disk IO counters
counters1, _ := disk.IOCounters()
time.Sleep(time.Second)
// Get disk IO counters after 1 second
counters2, _ := disk.IOCounters()
for device, counter1 := range counters1 {
counter2 := counters2[device]
readSpeed := float64(counter2.ReadBytes-counter1.ReadBytes) / 1024
writeSpeed := float64(counter2.WriteBytes-counter1.WriteBytes) / 1024
fmt.Printf("%v: read %vKB/s, write %vKB/s\n", device, readSpeed, writeSpeed)
}
}

View File

@@ -0,0 +1,22 @@
package status
import (
"encoding/json"
"fmt"
"testing"
)
func TestGetDiskStatus(t *testing.T) {
ds := GetDiskStatus()
fmt.Printf("Total: %v, Used: %v\n", ds.Total, ds.Used)
fmt.Printf("Logical Disks: %v\n", ds.LogicalDisk)
marshalIndent, err := json.MarshalIndent(ds, "", " ")
if err != nil {
fmt.Printf("error")
}
fmt.Println(string(marshalIndent))
}

44
agent-go/status/Memory.go Normal file
View File

@@ -0,0 +1,44 @@
package status
import (
"fmt"
"github.com/shirou/gopsutil/v3/mem"
)
type MemoryStatus struct {
TotalMemory uint64
UsedMemory uint64
AvailableMemory uint64
TotalVirtualMemory uint64
UsedVirtualMemory uint64
}
func GetMemoryStatus() (*MemoryStatus, error) {
memoryStatus := &MemoryStatus{}
virtualMemoryStat, err := mem.VirtualMemory()
if err != nil {
return memoryStatus, err
}
memoryStatus.TotalMemory = virtualMemoryStat.Total
memoryStatus.UsedMemory = virtualMemoryStat.Used
memoryStatus.AvailableMemory = virtualMemoryStat.Available
memoryStatus.TotalVirtualMemory = virtualMemoryStat.Total
memoryStatus.UsedVirtualMemory = virtualMemoryStat.Used
return memoryStatus, nil
}
func FormatMemorySize(size uint64) string {
const unit = 1024
if size < unit {
return fmt.Sprintf("%d B", size)
}
div, exp := int64(unit), 0
for n := size / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB", float64(size)/float64(div), "KMGTPE"[exp])
}

View File

@@ -0,0 +1,28 @@
package status
import (
"encoding/json"
"fmt"
"testing"
)
func TestGetMemoryStatus(t *testing.T) {
memoryStatus, err := GetMemoryStatus()
if err != nil {
return
}
fmt.Printf("Total Memory: %s\n", FormatMemorySize(memoryStatus.TotalMemory))
fmt.Printf("Used Memory: %s\n", FormatMemorySize(memoryStatus.UsedMemory))
fmt.Printf("Available Memory: %s\n", FormatMemorySize(memoryStatus.AvailableMemory))
fmt.Printf("Total Virtual Memory: %s\n", FormatMemorySize(memoryStatus.TotalVirtualMemory))
fmt.Printf("Used Virtual Memory: %s\n", FormatMemorySize(memoryStatus.UsedVirtualMemory))
marshalIndent, err := json.MarshalIndent(memoryStatus, "", " ")
if err != nil {
fmt.Printf("error")
}
fmt.Println(string(marshalIndent))
}

122
agent-go/status/Network.go Normal file
View File

@@ -0,0 +1,122 @@
package status
import (
"fmt"
"github.com/shirou/gopsutil/v3/net"
net2 "net"
"strings"
"time"
)
type NetworkStatus struct {
Name string `json:"name,omitempty"`
InternalIPv4 []string `json:"internal_ip_v4,omitempty"`
InternalIPv6 []string `json:"internal_ip_v6,omitempty"`
ExternalIPv4 []string `json:"external_ip_v4,omitempty"`
ExternalIPv6 []string `json:"external_ip_v6,omitempty"`
Mac string `json:"mac,omitempty"`
Sent uint64 `json:"sent,omitempty"`
Recv uint64 `json:"recv,omitempty"`
SentRate string `json:"sent_rate,omitempty"`
RecvRate string `json:"recv_rate,omitempty"`
}
func GetNetworkStatus() (*NetworkStatus, error) {
interfaces, err := net.Interfaces()
if err != nil {
return nil, err
}
var mainInterface net.InterfaceStat
for _, intf := range interfaces {
if strings.HasPrefix(intf.Name, "ens") || strings.HasPrefix(intf.Name, "eth") || strings.HasPrefix(intf.Name, "eno") {
mainInterface = intf
break
}
}
var allAddrs []string
log.DebugF("all main interface address are %v", mainInterface.Addrs)
for _, addr := range mainInterface.Addrs {
allAddrs = append(allAddrs, addr.Addr)
}
ipv4List, ipv6List := GetInternelIpAddrs(allAddrs)
log.DebugF("ipv4 list are => %v, ipv6 list are => %v", ipv4List, ipv6List)
counters, err := net.IOCounters(true)
if err != nil {
return nil, err
}
var sent uint64
var recv uint64
for _, counter := range counters {
if counter.Name == mainInterface.Name {
sent = counter.BytesSent
recv = counter.BytesRecv
break
}
}
// 休眠3秒
time.Sleep(3 * time.Second)
var sentAfter uint64
var recvAfter uint64
countersAfter, err := net.IOCounters(true)
if err != nil {
return nil, err
}
for _, counter := range countersAfter {
if counter.Name == mainInterface.Name {
sentAfter = counter.BytesSent
recvAfter = counter.BytesRecv
break
}
}
sendRate := fmt.Sprintf(formatBytes((sentAfter-sent)/3) + "/s")
recvRate := fmt.Sprintf(formatBytes((recvAfter-recv)/3) + "/s")
info := &NetworkStatus{
Name: mainInterface.Name,
InternalIPv4: ipv4List,
InternalIPv6: ipv6List,
ExternalIPv4: nil,
ExternalIPv6: nil,
Mac: mainInterface.HardwareAddr,
Sent: sent,
Recv: recv,
SentRate: sendRate,
RecvRate: recvRate,
}
return info, nil
}
func formatBytes(bytes uint64) string {
const unit = 1024
if bytes < unit {
return fmt.Sprintf("%d B", bytes)
}
div, exp := int64(unit), 0
for n := bytes / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
}
func GetInternelIpAddrs(addresses []string) ([]string, []string) {
var ipv4 []string
var ipv6 []string
for _, addr := range addresses {
// it parse (0.0.0.0) not cidr
ip, _, err := net2.ParseCIDR(addr)
if err != nil {
continue
}
if ip.To4() != nil {
ipv4 = append(ipv4, addr)
} else if ip.To16() != nil {
ipv6 = append(ipv6, addr)
}
}
return ipv4, ipv6
}

View File

@@ -0,0 +1,22 @@
package status
import (
"encoding/json"
"fmt"
"testing"
)
func TestGetNetworkInfo(t *testing.T) {
networkInfo, err := GetNetworkStatus()
if err != nil {
return
}
marshalIndent, err := json.MarshalIndent(networkInfo, "", " ")
if err != nil {
fmt.Printf("error")
}
fmt.Println(string(marshalIndent))
}

63
agent-go/status/Status.go Normal file
View File

@@ -0,0 +1,63 @@
package status
import (
logger2 "agent-go/logger"
"fmt"
"time"
)
var log = logger2.Log
type StatusMessage struct {
/**
* which kind of status should be return
"PING";
* METRIC => short time message
* ALL => all agent status message
* */
StatusType string `json:"statusType,omitempty"`
MetricRepeatCount int `json:"metricRepeatCount,omitempty"`
metricRepeatPinch int `json:"metricRepeatPinch,omitempty"`
}
type AgentStatus struct {
CPUStatus *CPUStatus
MemoryStatus *MemoryStatus
NetworkStatus *NetworkStatus
DiskStatus *DiskStatus
}
func ConvertToFormat(eventData float64) string {
duration := time.Duration(eventData) * time.Second
fmt.Println(duration)
hours := int(duration.Hours())
minutes := int(duration.Minutes()) % 60
seconds := int(duration.Seconds()) % 60
milliseconds := duration.Milliseconds() % 1000
return fmt.Sprintf("%02d:%02d:%02d,%03d", hours, minutes, seconds, milliseconds)
}
func Ping() string {
return "PONG"
}
func ReportAppStatus() *AgentStatus {
cpuStatus, cpuerr := GetCPUStatus()
memoryStatus, memerr := GetMemoryStatus()
networkStatus, neterr := GetNetworkStatus()
if cpuerr != nil || memerr != nil || neterr != nil {
log.ErrorF("获取Agent的状态出现错误 请检查")
return nil
}
diskStatus := GetDiskStatus()
return &AgentStatus{
CPUStatus: cpuStatus,
MemoryStatus: memoryStatus,
NetworkStatus: networkStatus,
DiskStatus: diskStatus,
}
}

View File

@@ -0,0 +1,26 @@
package status
import (
"encoding/json"
"fmt"
"testing"
)
func TestConvertToFormat(t *testing.T) {
convertToFormat := ConvertToFormat(99.92)
fmt.Println(convertToFormat)
}
func TestReportAppStatus(t *testing.T) {
agentStatus := ReportAppStatus()
marshal, err := json.Marshal(agentStatus)
if err != nil {
return
}
fmt.Printf(string(marshal))
}

7
agent-go/tmp/1.sh Normal file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
export http_proxy=http://10.250.0.10:10810 && export https_proxy=http://10.250.0.10:10810

View File

@@ -0,0 +1,8 @@
{
"uuid": "2023-03-27 14:38:49",
"init_time": "2023-03-27T14:38:49.8162801+08:00",
"type": "EXECUTOR",
"content": "{\n \"needResultReplay\": true,\n \"durationTask,default:false\": false,\n \"type\": \"pipeline\",\n \"singleLineCommand\": null,\n \"multiLineCommand\": [[\"ls\",\"-l\"],[\"pwd\"]],\n \"pipeLineCommand\": null,\n \"resultKey\": \"output\"\n}",
"result": "",
"ac_time": "0001-01-01T00:00:00Z"
}

View File

@@ -0,0 +1,9 @@
{
"uuid": "2023-03-27 14:38:49",
"init_time": "2023-03-27T14:38:49.8162801+08:00",
"type": "EXECUTOR",
"content": "{\n \"needResultReplay\": true,\n \"durationTask,default:false\": false,\n \"type\": \"pipeline\",\n \"singleLineCommand\": null,\n \"multiLineCommand\": null,\n \"pipeLineCommand\": [[\"ls\",\"-la\"],[\"grep\", \"dev\"],[\"awk\",\"{print $9}\"]],\n \"resultKey\": \"output\"\n}\n",
"result": "",
"ac_time": "0001-01-01T00:00:00Z"
}

View File

@@ -2,7 +2,7 @@
"uuid": "2023-03-27 14:38:49", "uuid": "2023-03-27 14:38:49",
"init_time": "2023-03-27T14:38:49.8162801+08:00", "init_time": "2023-03-27T14:38:49.8162801+08:00",
"type": "EXECUTOR", "type": "EXECUTOR",
"content": "{\n \"needResultReplay\": true,\n \"durationTask,default:false\": false,\n \"type\": \"command\",\n \"singleLineCommand\": [\n \"ls\",\n \"-la\"\n ],\n \"multiLineCommand\": null,\n \"pipeLineCommand\": null,\n \"resultKey\": \"output\"\n}\n", "content": "{\n \"needResultReplay\": true,\n \"durationTask,default:false\": false,\n \"type\": \"command\",\n \"singleLineCommand\": [\n \"ls\",\n \"-l\"\n ],\n \"multiLineCommand\": null,\n \"pipeLineCommand\": null,\n \"resultKey\": \"output\"\n}\n",
"result": "", "result": "",
"ac_time": "0001-01-01T00:00:00Z" "ac_time": "0001-01-01T00:00:00Z"
} }

View File

@@ -0,0 +1,5 @@
{
"uuid\":\"Chengdu-amd64-98-fakema\",\"init_time\":\"2023-06-19 15:21:02\",\"type\":\"INIT\",\"content\":\"{\\\"serverName\\\":\\\"Chengdu-amd64-98\\\",\\\"serverIpPbV4\\\":\\\"183.220.149.17\\\",\\\"serverIpInV4\\\":\\\"\\\",\\\"serverIpPbV6\\\":\\\"\\\",\\\"serverIpInV6\\\":\\\"\\\",\\\"registerTime\\\":null,\\\"expireTime\\\":null,\\\"createTime\\\":null,\\\"updateTime\\\":null,\\\"proxyType\\\":null,\\\"location\\\":\\\"Chengdu Sichuan CN\\\",\\\"provider\\\":\\\"AS139080 The Internet Data Center of Sichuan Mobile Communication Company Limited\\\",\\\"managePort\\
\
":\\\"22\\\",\\\"cpuBrand\\\":\\\"Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz\\\",\\\"cpuCore\\\":\\\"12 @ 4299.998 MHz\\\",\\\"memoryTotal\\\":\\\"7.6 GB\\\",\\\"diskTotal\\\":\\\"914.9 GB\\\",\\\"diskUsage\\\":\\\"12.3 GB\\\",\\\"ioSpeed\\\":\\\"150 MB/s\\\",\\\"tcpControl\\\":\\\"cubic\\\",\\\"virtualization\\\":\\\"Dedicated\\\",\\\"osInfo\\\":\\\"Ubuntu 20.04.5 LTS\\\",\\\"osKernelInfo\\\":\\\"5.4.0-135-generic\\\",\\\"machineId\\\":\\\"fakemachinid123\\\",\\\"topicName\\\":\\\"Chengdu-amd64-98-fakema\\\",\\\"comment\\\":\\\"\\\",\\\"agentVersion\\\":\\\"\\\"}\",\"result\":null,\"ac_time\":null}"
}

View File

@@ -0,0 +1,8 @@
{
"uuid": "2023-06-19 14:29:20",
"init_time": "2023-06-19 14:29:20",
"type": "INIT",
"content": "{\"serverName\":\"Chengdu-amd64-98\",\"serverIpPbV4\":\"183.220.149.17\",\"serverIpInV4\":\"\",\"serverIpPbV6\":\"\",\"serverIpInV6\":\"\",\"location\":\"Chengdu Sichuan CN\",\"provider\":\"AS139080 The Internet Data Center of Sichuan Mobile Communication Company Limited\",\"managePort\":\"22\",\"cpuCore\":\"12 @ 4299.998 MHz\",\"cpuBrand\":\"Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz\",\"osInfo\":\"Ubuntu 20.04.5 LTS\",\"osKernelInfo\":\"5.4.0-135-generic\",\"tcpControl\":\"cubic\",\"virtualization\":\"Dedicated\",\"ioSpeed\":\"150 MB/s\",\"memoryTotal\":\"7.6 GB\",\"diskTotal\":\"914.9 GB\",\"diskUsage\":\"12.3 GB\",\"comment\":\"\",\"machineId\":\"\",\"agentVersion\":\"\",\"agentTopicName\":\"\"}",
"result": null,
"ac_time": "2023-06-19 14:29:20"
}

Binary file not shown.

View File

@@ -0,0 +1 @@
92a968c0d5msh36a70a2da667c96p1bcc99jsnae97d91732f3

7
agent-go/tmp/simple.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
for i in {1..30}
do
echo "yes"
sleep 0.3
done

View File

@@ -0,0 +1,8 @@
{
"uuid": "2023-03-27 14:38:49",
"init_time": "2023-03-27T14:38:49.8162801+08:00",
"type": "STATUS",
"content": "{\n\"type\": \"status\",\n\"agent_topic_name\": \"exampleAgentTopicName\",\n\"metric_repeat_count\": 0,\n\"metric_repeat_pinch\": 0\n}",
"result": "",
"ac_time": "0001-01-01T00:00:00Z"
}

View File

@@ -0,0 +1,8 @@
{
"uuid": "2023-03-27 14:38:49",
"init_time": "2023-03-27T14:38:49.8162801+08:00",
"type": "STATUS",
"content": "{\n\"type\": \"ping\",\n\"agent_topic_name\": \"exampleAgentTopicName\",\n\"metric_repeat_count\": 0,\n\"metric_repeat_pinch\": 0\n}",
"result": "",
"ac_time": "0001-01-01T00:00:00Z"
}

View File

@@ -4,13 +4,18 @@ import (
"time" "time"
) )
// CurTimeString 输出系统时间的格式为"2006-01-02 15:04:05"形式的时间字符串 // ParseDateTimeTime 输出系统时间的格式为"2006-01-02 15:04:05"形式的时间字符串
func CurTimeString() string { func ParseDateTimeTime() string {
now := time.Now() now := time.Now()
/*loc := time.FixedZone("UTC+8", 8*60*60) // 创建东八区时区对象 /*loc := time.FixedZone("UTC+8", 8*60*60) // 创建东八区时区对象
localTime := now.In(loc) // 转换为东八区时间*/ localTime := now.In(loc) // 转换为东八区时间*/
return now.Format("2006-01-02 15:04:05") return now.Format(time.DateTime)
}
func ParseISOLocalDateTime() string {
now := time.Now()
return now.Format(time.RFC3339)
} }

View File

@@ -30,7 +30,15 @@ public class OMHandlerExecutor extends AbstractOctopusMessageHandler {
@Override @Override
public boolean handle(OctopusMessage octopusMessage) { public boolean handle(OctopusMessage octopusMessage) {
if (!octopusMessage if (!octopusMessage
.getType() .getType()
.equals(OctopusMessageType.EXECUTOR)) { .equals(OctopusMessageType.EXECUTOR)) {
return next.handle(octopusMessage); return next.handle(octopusMessage);
@@ -41,6 +49,7 @@ public class OMHandlerExecutor extends AbstractOctopusMessageHandler {
try { try {
// 需要首先解析成 ExecutionMessage // 需要首先解析成 ExecutionMessage
ExecutionMessage executionMessage = objectMapper.readValue( ExecutionMessage executionMessage = objectMapper.readValue(
(String) octopusMessage.getContent(), (String) octopusMessage.getContent(),
new TypeReference<ExecutionMessage>() { new TypeReference<ExecutionMessage>() {

View File

@@ -0,0 +1,5 @@
package io.wdd.agent;
public class CommandTest {
}

View File

@@ -27,6 +27,10 @@
<artifactId>oshi-core-java11</artifactId> <artifactId>oshi-core-java11</artifactId>
<version>6.4.0</version> <version>6.4.0</version>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
</dependencies> </dependencies>

View File

@@ -1,13 +1,13 @@
package io.wdd.common; package io.wdd.common;
import org.springframework.boot.SpringApplication; //import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; //import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication //@SpringBootApplication
public class CommonApplication { //public class CommonApplication {
//
public static void main(String[] args) { // public static void main(String[] args) {
SpringApplication.run(CommonApplication.class, args); // SpringApplication.run(CommonApplication.class, args);
} // }
//
} //}

View File

@@ -1,36 +0,0 @@
package io.wdd.common.beans.status;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class OctopusStatusMessage {
// below two will be used by both server and agent
// 存储所有Agent的实时健康状态 1代表健康 0代表失败
public static final String ALL_AGENT_STATUS_REDIS_KEY = "ALL_AGENT_HEALTHY_STATUS";
public static final String HEALTHY_STATUS_MESSAGE_TYPE = "ping";
public static final String ALL_STATUS_MESSAGE_TYPE = "all";
public static final String METRIC_STATUS_MESSAGE_TYPE = "metric";
public static final String APP_STATUS_MESSAGE_TYPE = "app";
/**
* which kind of status should be return
* metric => short time message
* all => all agent status message
* healthy => check for healthy
* */
String type;
String agentTopicName;
int metricRepeatCount;
int metricRepeatPinch;
}

138
pom.xml
View File

@@ -20,10 +20,10 @@
<description>ProjectOctopus</description> <description>ProjectOctopus</description>
<modules> <modules>
<module>agent</module>
<module>server</module> <module>server</module>
<!--<module>agent</module>
<module>common</module> <module>common</module>
<module>source</module> <module>source</module>-->
</modules> </modules>
<properties> <properties>
@@ -36,101 +36,6 @@
<dependencies> <dependencies>
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>-->
<!-- spring cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud alibaba dependency -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${alibaba-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.1.5</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${alibaba-cloud.version}</version>
</dependency>
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--<dependency>
<groupId>org.springframework.shell</groupId>
<artifactId>spring-shell-starter</artifactId>
</dependency>-->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
<!-- rabbitmq dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- redis dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.6</version>
</dependency>-->
<!-- lettuce pool 缓存连接池-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--<dependency> <!--<dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@@ -139,11 +44,42 @@
<optional>true</optional> <optional>true</optional>
</dependency>--> </dependency>-->
<dependency> <!--<dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
<scope>test</scope> </dependency>-->
</dependency>
<!-- spring cloud -->
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>-->
<!-- spring cloud alibaba dependency -->
<!--<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${alibaba-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>-->
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.1.5</version>
</dependency>-->
<!--<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${alibaba-cloud.version}</version>
</dependency>-->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>-->
</dependencies> </dependencies>

View File

@@ -21,9 +21,37 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>io.wdd</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>common</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>${project.parent.version}</version> </dependency>
<!-- rabbitmq dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- redis dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.6</version>
</dependency>-->
<!-- lettuce pool 缓存连接池-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency> </dependency>
<!-- add in 2023-02-08 needed for some operation --> <!-- add in 2023-02-08 needed for some operation -->
@@ -67,12 +95,32 @@
<version>3.5.2</version> <version>3.5.2</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<!--<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>org.apache.commons</groupId>
<artifactId>druid</artifactId> <artifactId>commons-lang3</artifactId>
<version>1.1.19</version> <version>3.12.0</version>
</dependency>--> </dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core-java11</artifactId>
<version>6.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency> <dependency>
@@ -87,6 +135,12 @@
<scope>runtime</scope> <scope>runtime</scope>
</dependency>--> </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<dependencyManagement> <dependencyManagement>

View File

@@ -8,6 +8,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("io.wdd.server.mapper") @MapperScan("io.wdd.server.mapper")
public class ServerApplication { public class ServerApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args); SpringApplication.run(ServerApplication.class, args);
} }

View File

@@ -1,8 +1,8 @@
package io.wdd.common.handler; package io.wdd.common.handler;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import io.wdd.common.beans.response.R; import io.wdd.common.response.R;
import io.wdd.common.beans.response.ResultStat; import io.wdd.common.response.ResultStat;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.support.ListenerExecutionFailedException; import org.springframework.amqp.rabbit.support.ListenerExecutionFailedException;

View File

@@ -1,6 +1,6 @@
package io.wdd.common.handler; package io.wdd.common.handler;
import io.wdd.common.beans.response.ResultStat; import io.wdd.common.response.ResultStat;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

View File

@@ -1,4 +1,4 @@
package io.wdd.common.beans.response; package io.wdd.common.response;
import lombok.Data; import lombok.Data;

View File

@@ -1,4 +1,4 @@
package io.wdd.common.beans.response; package io.wdd.common.response;
public enum ResultStat { public enum ResultStat {

View File

@@ -1,8 +1,8 @@
package io.wdd.common.utils; package io.wdd.common.utils;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.wdd.common.beans.rabbitmq.OctopusMessage;
import io.wdd.common.handler.MyRuntimeException; import io.wdd.common.handler.MyRuntimeException;
import io.wdd.rpc.message.OctopusMessage;
import org.springframework.amqp.core.Message; import org.springframework.amqp.core.Message;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@@ -1,12 +1,15 @@
package io.wdd.common.utils; package io.wdd.common.utils;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@@ -14,6 +17,16 @@ import java.time.format.DateTimeFormatter;
@Configuration @Configuration
public class OctopusObjectMapperConfig { public class OctopusObjectMapperConfig {
public static ObjectMapper OctopusObjectMapper = null;
@Resource
ObjectMapper objectMapper;
@PostConstruct
public void setOctopusObjectMapper() {
OctopusObjectMapper = objectMapper;
}
public static Jackson2ObjectMapperBuilderCustomizer common() { public static Jackson2ObjectMapperBuilderCustomizer common() {
return jacksonObjectMapperBuilder -> { return jacksonObjectMapperBuilder -> {

View File

@@ -8,7 +8,6 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;

View File

@@ -7,7 +7,7 @@ import com.amazonaws.services.s3.model.S3Object;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import io.wdd.common.beans.response.R; import io.wdd.common.response.R;
import io.wdd.func.oss.config.OctopusObjectSummary; import io.wdd.func.oss.config.OctopusObjectSummary;
import io.wdd.func.oss.config.OssConfig; import io.wdd.func.oss.config.OssConfig;
import io.wdd.func.oss.service.OSSCoreService; import io.wdd.func.oss.service.OSSCoreService;

View File

@@ -4,7 +4,7 @@ package io.wdd.func.controller;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import io.wdd.common.beans.response.R; import io.wdd.common.response.R;
import io.wdd.func.xray.beans.node.ProxyNode; import io.wdd.func.xray.beans.node.ProxyNode;
import io.wdd.func.xray.beans.node.XrayConfigInfo; import io.wdd.func.xray.beans.node.XrayConfigInfo;
import io.wdd.func.xray.service.XrayCallAgent; import io.wdd.func.xray.service.XrayCallAgent;

View File

@@ -3,7 +3,7 @@ package io.wdd.func.xray.service;
import io.wdd.common.utils.TimeUtils; import io.wdd.common.utils.TimeUtils;
import io.wdd.func.oss.config.OctopusObjectSummary; import io.wdd.func.oss.config.OctopusObjectSummary;
import io.wdd.func.xray.beans.node.ProxyNode; import io.wdd.func.xray.beans.node.ProxyNode;
import io.wdd.rpc.execute.service.AsyncExecutionService; import io.wdd.rpc.execute.service.SyncExecutionService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -83,7 +83,7 @@ public class XrayCallAgent {
} }
@Resource @Resource
AsyncExecutionService executionService; SyncExecutionService executionService;
/** /**
* 为代理链的每一个节点 构建Xray配置更新命令然后发送至对应的Agent中 * 为代理链的每一个节点 构建Xray配置更新命令然后发送至对应的Agent中
@@ -131,7 +131,7 @@ public class XrayCallAgent {
); );
// 向Agent发送命令执行更新操作 // 向Agent发送命令执行更新操作
String resultKey = executionService.SendCommandToAgent( String resultKey = executionService.SyncSendCommandToAgent(
proxyNode.getAgentTopicName(), proxyNode.getAgentTopicName(),
updateCommandType, updateCommandType,
null, null,

View File

@@ -1,4 +1,4 @@
package io.wdd.common.beans.agent; package io.wdd.rpc.agent;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@@ -1,4 +1,4 @@
package io.wdd.common.beans.agent; package io.wdd.rpc.agent;
public enum AgentOperationType { public enum AgentOperationType {

View File

@@ -3,13 +3,11 @@ package io.wdd.rpc.agent;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.wdd.common.beans.agent.AgentOperationMessage;
import io.wdd.common.beans.agent.AgentOperationType;
import io.wdd.common.beans.rabbitmq.OctopusMessage;
import io.wdd.common.beans.rabbitmq.OctopusMessageType;
import io.wdd.common.utils.TimeUtils; import io.wdd.common.utils.TimeUtils;
import io.wdd.rpc.message.handler.AsyncWaitOMResult; import io.wdd.rpc.message.OctopusMessage;
import io.wdd.rpc.message.handler.OMReplayContend; import io.wdd.rpc.message.OctopusMessageType;
import io.wdd.rpc.message.handler.async.AsyncWaitOctopusMessageResultService;
import io.wdd.rpc.message.handler.async.OctopusMessageAsyncReplayContend;
import io.wdd.rpc.message.sender.OMessageToAgentSender; import io.wdd.rpc.message.sender.OMessageToAgentSender;
import io.wdd.server.beans.vo.ServerInfoVO; import io.wdd.server.beans.vo.ServerInfoVO;
import io.wdd.server.config.ServerCommonPool; import io.wdd.server.config.ServerCommonPool;
@@ -28,10 +26,10 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static io.wdd.rpc.init.ServerCacheAgentStatus.ALL_AGENT_TOPIC_NAME_SET; import static io.wdd.rpc.init.AgentStatusCacheService.ALL_AGENT_TOPIC_NAME_SET;
import static io.wdd.rpc.init.ServerCacheAgentStatus.ALL_HEALTHY_AGENT_TOPIC_NAME_LIST; import static io.wdd.rpc.init.AgentStatusCacheService.ALL_HEALTHY_AGENT_TOPIC_NAME_LIST;
import static io.wdd.rpc.message.handler.OMessageHandlerServer.AGENT_LATEST_VERSION; import static io.wdd.rpc.message.handler.sync.OMessageHandlerServer.AGENT_LATEST_VERSION;
import static io.wdd.rpc.message.handler.OMessageHandlerServer.OCTOPUS_MESSAGE_FROM_AGENT; import static io.wdd.rpc.message.handler.sync.OMessageHandlerServer.OCTOPUS_MESSAGE_FROM_AGENT;
@Service @Service
@Slf4j @Slf4j
@@ -47,7 +45,7 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
RedisTemplate redisTemplate; RedisTemplate redisTemplate;
@Resource @Resource
AsyncWaitOMResult asyncWaitOMResult; AsyncWaitOctopusMessageResultService asyncWaitOctopusMessageResultService;
@Override @Override
public Map<String, String> getAllAgentVersion() { public Map<String, String> getAllAgentVersion() {
@@ -72,17 +70,17 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
); );
// 构造 异步结果监听内容 // 构造 异步结果监听内容
OMReplayContend omReplayContend = OMReplayContend.build( OctopusMessageAsyncReplayContend agentReplayContend = OctopusMessageAsyncReplayContend.build(
ALL_HEALTHY_AGENT_TOPIC_NAME_LIST.size(), ALL_HEALTHY_AGENT_TOPIC_NAME_LIST.size(),
CurrentAppOctopusMessageType, CurrentAppOctopusMessageType,
currentTime currentTime
); );
CountDownLatch countDownLatch = omReplayContend.getCountDownLatch(); CountDownLatch countDownLatch = agentReplayContend.getCountDownLatch();
// 调用后台接收处理所有的Replay信息 // 调用后台接收处理所有的Replay信息
asyncWaitOMResult.waitFor(omReplayContend); asyncWaitOctopusMessageResultService.waitFor(agentReplayContend);
//此处存在重大bug,会导致CPU占用飙升 //此处存在重大bug,会导致CPU占用飙升
/*CompletableFuture<Void> getAllAgentVersionInfoFuture = waitCollectAllAgentVersionInfo( /*CompletableFuture<Void> getAllAgentVersionInfoFuture = waitCollectAllAgentVersionInfo(
@@ -108,10 +106,10 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
} }
// 此处调用,即可中断 异步任务的收集工作 // 此处调用,即可中断 异步任务的收集工作
asyncWaitOMResult.stopWaiting(omReplayContend); asyncWaitOctopusMessageResultService.stopWaiting(agentReplayContend);
// 处理结果 // 处理结果
omReplayContend agentReplayContend
.getReplayOMList() .getReplayOMList()
.stream() .stream()
.forEach( .forEach(
@@ -124,7 +122,7 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
); );
// help gc // help gc
omReplayContend = null; agentReplayContend = null;
} }
return result; return result;
@@ -158,16 +156,16 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
); );
// 构造结果 // 构造结果
OMReplayContend omReplayContend = OMReplayContend.build( OctopusMessageAsyncReplayContend OctopusMessageAsyncReplayContend = io.wdd.rpc.message.handler.async.OctopusMessageAsyncReplayContend.build(
ALL_HEALTHY_AGENT_TOPIC_NAME_LIST.size(), ALL_HEALTHY_AGENT_TOPIC_NAME_LIST.size(),
CurrentAppOctopusMessageType, CurrentAppOctopusMessageType,
currentTime currentTime
); );
CountDownLatch countDownLatch = omReplayContend.getCountDownLatch(); CountDownLatch countDownLatch = OctopusMessageAsyncReplayContend.getCountDownLatch();
// 调用后台接收处理所有的Replay信息 // 调用后台接收处理所有的Replay信息
asyncWaitOMResult.waitFor(omReplayContend); asyncWaitOctopusMessageResultService.waitFor(OctopusMessageAsyncReplayContend);
/* CompletableFuture<Void> getAllAgentCoreInfoFuture = waitCollectAllAgentCoreInfo( /* CompletableFuture<Void> getAllAgentCoreInfoFuture = waitCollectAllAgentCoreInfo(
result, result,
@@ -187,10 +185,10 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
// 超时,或者 全部信息已经收集 // 超时,或者 全部信息已经收集
// 此处调用,即可中断 异步任务的收集工作 // 此处调用,即可中断 异步任务的收集工作
asyncWaitOMResult.stopWaiting(omReplayContend); asyncWaitOctopusMessageResultService.stopWaiting(OctopusMessageAsyncReplayContend);
// 处理结果 // 处理结果
omReplayContend OctopusMessageAsyncReplayContend
.getReplayOMList() .getReplayOMList()
.stream() .stream()
.forEach( .forEach(
@@ -218,7 +216,7 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
); );
// help gc // help gc
omReplayContend = null; OctopusMessageAsyncReplayContend = null;
} }
return result; return result;

View File

@@ -2,7 +2,7 @@ package io.wdd.rpc.controller;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.wdd.common.beans.response.R; import io.wdd.common.response.R;
import io.wdd.rpc.agent.OctopusAgentService; import io.wdd.rpc.agent.OctopusAgentService;
import io.wdd.server.beans.vo.ServerInfoVO; import io.wdd.server.beans.vo.ServerInfoVO;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;

Some files were not shown because too many files have changed in this diff Show More