Repository: 1Panel-dev/1Panel
Pull request #8413: feat: Supervisor supports automatic restart configuration.
Author: login: zhengkunwang223
Labels: name: do-not-merge/release-note-label-needed
name: approved
name: dev-v2
Created: 2025-04-17T03:33:06Z | Merged: 2025-04-17T14:22:24Z

Refs https://github.com/1Panel-dev/1Panel/issues/7406


Diff:
diff --git a/agent/app/dto/request/host_tool.go b/agent/app/dto/request/host_tool.go
index 9d602a19aa5c..bbd9ee6916ae 100644
--- a/agent/app/dto/request/host_tool.go
+++ b/agent/app/dto/request/host_tool.go
@@ -26,12 +26,13 @@ type HostToolConfig struct {
 }
 
 type SupervisorProcessConfig struct {
-	Name     string `json:"name"`
-	Operate  string `json:"operate"`
-	Command  string `json:"command"`
-	User     string `json:"user"`
-	Dir      string `json:"dir"`
-	Numprocs string `json:"numprocs"`
+	Name        string `json:"name"`
+	Operate     string `json:"operate"`
+	Command     string `json:"command"`
+	User        string `json:"user"`
+	Dir         string `json:"dir"`
+	Numprocs    string `json:"numprocs"`
+	AutoRestart string `json:"autoRestart"`
 }
 
 type SupervisorProcessFileReq struct {
diff --git a/agent/app/dto/response/host_tool.go b/agent/app/dto/response/host_tool.go
index e97a675d8ef8..0c7783736437 100644
--- a/agent/app/dto/response/host_tool.go
+++ b/agent/app/dto/response/host_tool.go
@@ -23,13 +23,14 @@ type HostToolConfig struct {
 }
 
 type SupervisorProcessConfig struct {
-	Name     string          `json:"name"`
-	Command  string          `json:"command"`
-	User     string          `json:"user"`
-	Dir      string          `json:"dir"`
-	Numprocs string          `json:"numprocs"`
-	Msg      string          `json:"msg"`
-	Status   []ProcessStatus `json:"status"`
+	Name        string          `json:"name"`
+	Command     string          `json:"command"`
+	User        string          `json:"user"`
+	Dir         string          `json:"dir"`
+	Numprocs    string          `json:"numprocs"`
+	Msg         string          `json:"msg"`
+	Status      []ProcessStatus `json:"status"`
+	AutoRestart string          `json:"autoRestart"`
 }
 
 type ProcessStatus struct {
diff --git a/agent/app/service/host_tool.go b/agent/app/service/host_tool.go
index bf29a2099c8c..145deb40adcf 100644
--- a/agent/app/service/host_tool.go
+++ b/agent/app/service/host_tool.go
@@ -322,7 +322,7 @@ func handleProcess(supervisordDir string, req request.SupervisorProcessConfig, c
 		}
 		_, _ = section.NewKey("command", strings.TrimSpace(req.Command))
 		_, _ = section.NewKey("directory", req.Dir)
-		_, _ = section.NewKey("autorestart", "true")
+		_, _ = section.NewKey("autorestart", req.AutoRestart)
 		_, _ = section.NewKey("startsecs", "3")
 		_, _ = section.NewKey("stdout_logfile", outLog)
 		_, _ = section.NewKey("stderr_logfile", errLog)
@@ -358,6 +358,8 @@ func handleProcess(supervisordDir string, req request.SupervisorProcessConfig, c
 		userKey.SetValue(req.User)
 		numprocsKey := section.Key("numprocs")
 		numprocsKey.SetValue(req.Numprocs)
+		autoRestart := section.Key("autorestart")
+		autoRestart.SetValue(req.AutoRestart)
 
 		if err = configFile.SaveTo(iniPath); err != nil {
 			return err
@@ -424,6 +426,9 @@ func handleProcessConfig(configDir, containerName string) ([]response.Supervisor
 			if numprocs, _ := section.GetKey("numprocs"); numprocs != nil {
 				config.Numprocs = numprocs.Value()
 			}
+			if autoRestart, _ := section.GetKey("autorestart"); autoRestart != nil {
+				config.AutoRestart = autoRestart.Value()
+			}
 			_ = getProcessStatus(&config, containerName)
 			result = append(result, config)
 		}
diff --git a/agent/i18n/lang/zh.yaml b/agent/i18n/lang/zh.yaml
index 46ba56905be7..f4717341a8a9 100644
--- a/agent/i18n/lang/zh.yaml
+++ b/agent/i18n/lang/zh.yaml
@@ -262,6 +262,7 @@ ErrDBNotExist: "数据库不存在"
 allow: "允许"
 deny: "禁止"
 OpenrestyNotFound: "Openresty 未安装"
+remoteIpIsNull: "IP 列表为空"
 
 #task
 TaskStart: "{{ .name }} 任务开始 [START]"
diff --git a/frontend/src/api/interface/host-tool.ts b/frontend/src/api/interface/host-tool.ts
index 3a5d00b9d2f5..ef3639a00f94 100644
--- a/frontend/src/api/interface/host-tool.ts
+++ b/frontend/src/api/interface/host-tool.ts
@@ -42,6 +42,7 @@ export namespace HostTool {
         dir: string;
         numprocs: string;
         status?: ProcessStatus[];
+        autoRestart: string;
     }
 
     export interface ProcessStatus {
diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts
index cf6a75dfb1ba..d14e41469fd6 100644
--- a/frontend/src/lang/modules/en.ts
+++ b/frontend/src/lang/modules/en.ts
@@ -2753,6 +2753,7 @@ const message = {
             ERROR: 'Error',
             statusCode: 'Status code',
             manage: 'Management',
+            autoRestart: 'Auto Restart',
         },
     },
     xpack: {
@@ -3013,6 +3014,7 @@ const message = {
             strict: 'Strict Mode',
             strictHelper: 'Use stricter rules to validate requests',
             saveLog: 'Save Log',
+            remoteURLHelper: 'The remote URL needs to ensure one IP per line and no other characters',
         },
         monitor: {
             name: 'Website Monitoring',
diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts
index 6470537c5106..fe90de8e1663 100644
--- a/frontend/src/lang/modules/ja.ts
+++ b/frontend/src/lang/modules/ja.ts
@@ -2619,6 +2619,7 @@ const message = {
             ERROR: 'エラー',
             statusCode: 'ステータスコード',
             manage: '管理',
+            autoRestart: '自動再起動',
         },
     },
     xpack: {
@@ -2873,6 +2874,7 @@ const message = {
             strict: '厳格モード',
             strictHelper: 'より厳格なルールを使用してリクエストを検証します',
             saveLog: 'ログを保存',
+            remoteURLHelper: 'リモート URL は、1行に1つのIPで、他の文字がないことを保証する必要があります',
         },
         monitor: {
             name: 'ウェブサイトモニタリング',
diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts
index 58e870ca33ff..5a542a3f4241 100644
--- a/frontend/src/lang/modules/ko.ts
+++ b/frontend/src/lang/modules/ko.ts
@@ -2578,6 +2578,7 @@ const message = {
             ERROR: '오류',
             statusCode: '상태 코드',
             manage: '관리',
+            autoRestart: '자동 재시작',
         },
     },
     xpack: {
@@ -2828,6 +2829,7 @@ const message = {
             strict: '엄격 모드',
             strictHelper: '더 엄격한 규칙을 사용하여 요청을 검증합니다',
             saveLog: '로그 저장',
+            remoteURLHelper: '원격 URL은 한 줄에 하나의 IP만 포함하고 다른 문자는 포함하지 않아야 합니다',
         },
         monitor: {
             name: '웹사이트 모니터링',
diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts
index 809de4a6629d..aab819a7bd20 100644
--- a/frontend/src/lang/modules/ms.ts
+++ b/frontend/src/lang/modules/ms.ts
@@ -2680,6 +2680,7 @@ const message = {
             ERROR: 'Ralat',
             statusCode: 'Kod status',
             manage: 'Pengurusan',
+            autoRestart: 'Auto Restart',
         },
     },
     xpack: {
@@ -2938,6 +2939,7 @@ const message = {
             strict: 'Mod Strict',
             strictHelper: 'Gunakan peraturan yang lebih ketat untuk mengesahkan permintaan',
             saveLog: 'Simpan Log',
+            remoteURLHelper: 'URL jauh perlu memastikan satu IP setiap baris dan tiada aksara lain',
         },
         monitor: {
             name: 'Pemantauan Laman Web',
diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts
index 47ddf6c998c3..97258ad84155 100644
--- a/frontend/src/lang/modules/pt-br.ts
+++ b/frontend/src/lang/modules/pt-br.ts
@@ -2677,6 +2677,7 @@ const message = {
             ERROR: 'Erro',
             statusCode: 'Código de status',
             manage: 'Gerenciamento',
+            autoRestart: 'Reinicialização Automática',
         },
     },
     xpack: {
@@ -2938,6 +2939,7 @@ const message = {
             strict: 'Modo estrito',
             strictHelper: 'Usa regras mais rigorosas para validar solicitações',
             saveLog: 'Salvar log',
+            remoteURLHelper: 'O URL remoto precisa garantir um IP por linha e nenhum outro caractere',
         },
         monitor: {
             name: 'Monitoramento de Websites',
diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts
index fb938414c5cc..50ca533a1015 100644
--- a/frontend/src/lang/modules/ru.ts
+++ b/frontend/src/lang/modules/ru.ts
@@ -2673,6 +2673,7 @@ const message = {
             ERROR: 'Ошибка',
             statusCode: 'Код статуса',
             manage: 'Управление',
+            autoRestart: 'Автоматический перезапуск',
         },
     },
     xpack: {
@@ -2932,6 +2933,7 @@ const message = {
             strict: 'Строгий режим',
             strictHelper: 'Использует более строгие правила для проверки запросов',
             saveLog: 'Сохранить лог',
+            remoteURLHelper: 'Удаленный URL должен содержать один IP на строку и не содержать других символов',
         },
         monitor: {
             name: 'Мониторинг веб-сайта',
diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts
index 65140d2ade6a..ee4943371b52 100644
--- a/frontend/src/lang/modules/zh-Hant.ts
+++ b/frontend/src/lang/modules/zh-Hant.ts
@@ -2550,6 +2550,7 @@ const message = {
             ERROR: '錯誤',
             statusCode: '狀態碼',
             manage: '管理',
+            autoRestart: '自動重啟',
         },
     },
     xpack: {
@@ -2793,6 +2794,7 @@ const message = {
             strict: '嚴格模式',
             strictHelper: '使用更嚴格的規則來校驗請求',
             saveLog: '保存日誌',
+            remoteURLHelper: '遠程 URL 需要保證每行一個 IP 並且沒有其他字符',
         },
         monitor: {
             name: '網站監控',
diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts
index 732acfe546ad..0029e873515b 100644
--- a/frontend/src/lang/modules/zh.ts
+++ b/frontend/src/lang/modules/zh.ts
@@ -2542,6 +2542,7 @@ const message = {
             ERROR: '错误',
             statusCode: '状态码',
             manage: '管理',
+            autoRestart: '自动重启',
         },
     },
     xpack: {
@@ -2782,6 +2783,7 @@ const message = {
             strict: '严格模式',
             strictHelper: '使用更严格的规则来校验请求',
             saveLog: '保存日志',
+            remoteURLHelper: '远程 URL 需要保证每行一个 IP 并且没有其他字符',
         },
         monitor: {
             name: '网站监控',
diff --git a/frontend/src/views/toolbox/supervisor/create/index.vue b/frontend/src/views/toolbox/supervisor/create/index.vue
index 09b7f6eb3065..a4e080976bba 100644
--- a/frontend/src/views/toolbox/supervisor/create/index.vue
+++ b/frontend/src/views/toolbox/supervisor/create/index.vue
@@ -30,6 +30,9 @@
             <el-form-item :label="$t('tool.supervisor.numprocs')" prop="numprocsNum">
                 <el-input type="number" v-model.number="process.numprocsNum"></el-input>
             </el-form-item>
+            <el-form-item :label="$t('tool.supervisor.autoRestart')" prop="autoRestart">
+                <el-switch v-model="process.autoRestart" active-value="true" inactive-value="false"></el-switch>
+            </el-form-item>
         </el-form>
         <template #footer>
             <span class="dialog-footer">
@@ -70,6 +73,7 @@ const initData = () => ({
     dir: '',
     numprocsNum: 1,
     numprocs: '1',
+    autoRestart: 'true',
 });
 const process = ref(initData());
 
@@ -100,6 +104,7 @@ const acceptParams = (operate: string, config: HostTool.SupersivorProcess) => {
             dir: config.dir,
             numprocsNum: 1,
             numprocs: config.numprocs,
+            autoRestart: config.autoRestart,
         };
         process.value.numprocsNum = Number(config.numprocs);
     }


Reviews:
user: login: wanghe-fit2cloud
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-17T03:33:26Z
user: login: wanghe-fit2cloud
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-17T03:33:39Z
user: login: wanghe-fit2cloud
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-17T03:33:43Z
user: login: wanghe-fit2cloud
body: /lgtm
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-17T14:20:52Z

Review comments:
diff_hunk: @@ -23,13 +23,14 @@ type HostToolConfig struct {
 }
 
 type SupervisorProcessConfig struct {
-	Name     string          `json:"name"`
-	Command  string          `json:"command"`
-	User     string          `json:"user"`
-	Dir      string          `json:"dir"`
-	Numprocs string          `json:"numprocs"`
-	Msg      string          `json:"msg"`
-	Status   []ProcessStatus `json:"status"`
+	Name        string          `json:"name"`
+	Command     string          `json:"command"`
+	User        string          `json:"user"`
+	Dir         string          `json:"dir"`
+	Numprocs    string          `json:"numprocs"`
+	Msg         string          `json:"msg"`
+	Status      []ProcessStatus `json:"status"`
+	AutoRestart string          `json:"autoRestart"`
 }
 
 type ProcessStatus struct {
path: agent/app/dto/response/host_tool.go
user: login: wanghe-fit2cloud
body: The provided code snippet is for `SupervisorProcessConfig`, which contains an additional field `AutoRestart` compared to the original struct definition in `HostToolConfig`. This seems like a mistake or intended change. The rest of the fields have not been altered.

**Irregularity**: The new field `AutoRestart` does not exist in the old struct `HostToolConfig`.

**Potential issues**: Without further context on whether this new field is necessary or how it fits into the existing system, there might be confusion about its purpose and potential integration bugs with other parts of the application.

**Optimization Suggestions**:

1. **Review Dependencies**: If including `AutoRestart` affects dependencies between components that interact with these structs, ensure they handle the new field appropriately.

2. **Documentation Update**: Clearly document the usage of `AutoRestart`, especially if it has functionality different from `Numprocs` as described in the comment above (`"If Numprocs == 'auto', then each proc will restart automatically after failure."`).

3. **Code Quality Checkers**: Run static analysis tools to identify such discrepancies early in development, which can help prevent inconsistencies at runtime.

4. **Consistency Check**: Compare all similar structures across the project to ensure consistency and avoid introducing errors in data integrity due to missing mandatory fields.

Overall, while having no immediate technical issue per se, updating documentation and ensuring consistent behavior could improve maintainability and clarity of the codebase.
created_at: 2025-04-17T03:33:26Z
author_association: MEMBER
diff_hunk: @@ -26,12 +26,13 @@ type HostToolConfig struct {
 }
 
 type SupervisorProcessConfig struct {
-	Name     string `json:"name"`
-	Operate  string `json:"operate"`
-	Command  string `json:"command"`
-	User     string `json:"user"`
-	Dir      string `json:"dir"`
-	Numprocs string `json:"numprocs"`
+	Name        string `json:"name"`
+	Operate     string `json:"operate"`
+	Command     string `json:"command"`
+	User        string `json:"user"`
+	Dir         string `json:"dir"`
+	Numprocs    string `json:"numprocs"`
+	AutoRestart string `json:"autoRestart"`
 }
 
 type SupervisorProcessFileReq struct {
path: agent/app/dto/request/host_tool.go
user: login: wanghe-fit2cloud
body: The provided JSON structure seems to be part of a configuration file used by Supervisord, an process control system for Unix-like operating systems. The main concern is that the `SupervisorProcessConfig` contains two fields with different names but similar functionality:

- `Numprocs`
- `AutoRestart`

It's not clear why these would have separate names (`"numprocs"` vs `"autoRestart"`) when they seem to represent the same concept: specifying a number of processes to start and whether to automatically restart them in case of failure.

Here are some suggestions for improvement:

1. **Consistency**: If `Numprocs` and `AutoRestart` should actually differ (e.g., if one controls automatic restarting while the other specifies the number of instances) then rename them appropriately based on their actual functions or usage within the Supervisor context.

2. **Documentation**: Ensure that this difference between `Numprocs` and `AutoRestart` is clearly documented so it’s understood what each field does.

3. **Default Values**: Consider setting default values for both fields to make configuration more flexible depending on specific use cases.

4. **Field Uniqueness**: Verify that no other code relies on these field names specifically to avoid potential bugs or unintended behaviors due to naming inconsistencies.

If you want to align the fields and provide clarity about how they relate to auto-restarting behavior, here's a revised version:

```go
type SupervisorProcessConfig struct {
    Name        string   `json:"name"`
    Operate     string   `json:"operate"`
    Command     string   `json:"command"`
    User        string   `json:"user"`
    Dir         string   `json:"dir"`
    NumInstances int       `json:"num_instances"` // Renamed as "num_instances"
    AutoRestart bool     `json:"auto Restart"` // Capitalized as per typical Go naming conventions
}
```

This revision maintains consistency while providing additional information through better naming and documentation practices.
created_at: 2025-04-17T03:33:39Z
author_association: MEMBER
diff_hunk: @@ -424,6 +426,9 @@ func handleProcessConfig(configDir, containerName string) ([]response.Supervisor
 			if numprocs, _ := section.GetKey("numprocs"); numprocs != nil {
 				config.Numprocs = numprocs.Value()
 			}
+			if autoRestart, _ := section.GetKey("autorestart"); autoRestart != nil {
+				config.AutoRestart = autoRestart.Value()
+			}
 			_ = getProcessStatus(&config, containerName)
 			result = append(result, config)
 		}
path: agent/app/service/host_tool.go
user: login: wanghe-fit2cloud
body: The provided code has no significant inaccuracies or issues. The `autoRestart` value is correctly retrieved from `req.AutoRestart`. No major optimizations can be suggested based on this patch; it appears to function as intended for setting up supervisor configurations in a given directory. If you need further modifications or have additional requirements, please provide more context or specify the changes needed.
created_at: 2025-04-17T03:33:43Z
author_association: MEMBER

PR comments:
user: login: f2c-ci-robot[bot]
created_at: 2025-04-17T03:33:10Z
body: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-04-17T03:34:40Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=1Panel-dev_1Panel&pullRequest=8413) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [1 New issue](https://sonarcloud.io/project/issues?id=1Panel-dev_1Panel&pullRequest=8413&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=1Panel-dev_1Panel&pullRequest=8413&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=1Panel-dev_1Panel&pullRequest=8413&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=1Panel-dev_1Panel&pullRequest=8413&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=1Panel-dev_1Panel&pullRequest=8413&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=1Panel-dev_1Panel&pullRequest=8413)


author_association: NONE
user: login: wanghe-fit2cloud
created_at: 2025-04-17T14:21:07Z
body: /approve
author_association: MEMBER
user: login: f2c-ci-robot[bot]
created_at: 2025-04-17T14:21:14Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/1Panel-dev/1Panel/pull/8413#issuecomment-2813109733" title="Approved">wanghe-fit2cloud</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=1Panel-dev%2F1Panel).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/1Panel-dev/1Panel/blob/dev-v2/OWNERS)~~ [wanghe-fit2cloud]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: NONE