Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 解决 Node 运行环境状态异常问题 #4197

Merged
merged 1 commit into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions backend/app/api/v1/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,19 @@ func (b *BaseApi) OperateNodeModules(c *gin.Context) {
}
helper.SuccessWithOutData(c)
}

// @Tags Runtime
// @Summary Sync runtime status
// @Description 同步运行环境状态
// @Accept json
// @Success 200
// @Security ApiKeyAuth
// @Router /runtimes/sync [post]
func (b *BaseApi) SyncStatus(c *gin.Context) {
err := runtimeService.SyncRuntimeStatus()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}
14 changes: 14 additions & 0 deletions backend/app/service/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type IRuntimeService interface {
GetNodeModules(req request.NodeModuleReq) ([]response.NodeModule, error)
OperateNodeModules(req request.NodeModuleOperateReq) error
SyncForRestart() error
SyncRuntimeStatus() error
}

func NewRuntimeService() IRuntimeService {
Expand Down Expand Up @@ -586,3 +587,16 @@ func (r *RuntimeService) SyncForRestart() error {
}
return nil
}

func (r *RuntimeService) SyncRuntimeStatus() error {
runtimes, err := runtimeRepo.List()
if err != nil {
return err
}
for _, runtime := range runtimes {
if runtime.Type == constant.RuntimeNode {
_ = SyncRuntimeContainerStatus(&runtime)
}
}
return nil
}
37 changes: 12 additions & 25 deletions backend/app/service/runtime_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,33 +181,20 @@ func SyncRuntimeContainerStatus(runtime *model.Runtime) error {
}
container := containers[0]

interval := 10 * time.Second
retries := 60
for i := 0; i < retries; i++ {
resp, err := cli.InspectContainer(container.ID)
if err != nil {
time.Sleep(interval)
continue
}
if resp.State.Health != nil {
status := strings.ToLower(resp.State.Health.Status)
switch status {
case "starting":
runtime.Status = constant.RuntimeStarting
_ = runtimeRepo.Save(runtime)
case "healthy":
runtime.Status = constant.RuntimeRunning
_ = runtimeRepo.Save(runtime)
return nil
case "unhealthy":
runtime.Status = constant.RuntimeUnhealthy
_ = runtimeRepo.Save(runtime)
return nil
}
switch container.State {
case "exited":
runtime.Status = constant.RuntimeError
case "running":
runtime.Status = constant.RuntimeRunning
case "paused":
runtime.Status = constant.RuntimeStopped
default:
if runtime.Status != constant.RuntimeBuildIng {
runtime.Status = constant.RuntimeStopped
}
time.Sleep(interval)
}
return nil

return runtimeRepo.Save(runtime)
}

func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) {
Expand Down
1 change: 1 addition & 0 deletions backend/router/ro_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func (r *RuntimeRouter) InitRouter(Router *gin.RouterGroup) {
groupRouter.POST("/del", baseApi.DeleteRuntime)
groupRouter.POST("/update", baseApi.UpdateRuntime)
groupRouter.GET("/:id", baseApi.GetRuntime)
groupRouter.POST("/sync", baseApi.SyncStatus)

groupRouter.POST("/node/package", baseApi.GetNodePackageRunScript)
groupRouter.POST("/operate", baseApi.OperateRuntime)
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/api/modules/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,7 @@ export const UpdatePHPExtensions = (req: Runtime.PHPExtensionsUpdate) => {
export const DeletePHPExtensions = (req: Runtime.PHPExtensionsDelete) => {
return http.post<any>(`/runtimes/php/extensions/del`, req);
};

export const SyncRuntime = () => {
return http.post(`/runtimes/sync`, {});
};
29 changes: 29 additions & 0 deletions frontend/src/lang/modules/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2240,6 +2240,35 @@ const message = {
javaFileter: 'Java Dangerous File Filtering',
scannerFilter: 'Scanner filter',
escapeFilter: 'escape filter',
customRule: 'custom rule',
httpMethod: 'HTTP method filter',
fileExt: 'File upload limit',
fileExtHelper: 'File extensions that are prohibited from uploading',
deny: 'forbidden',
allow: 'only allow',
field: 'match object',
pattern: 'matching condition',
ruleContent: 'match content',
contain: 'include',
equal: 'equal',
regex: 'regular expression',
notEqual: 'Not equal to',
customRuleHelper: 'Perform corresponding actions based on condition matching',
actionAllow: 'Allow',
blockIP: 'Block IP',
code: 'return status code',
noRes: 'Disconnect 444',
badReq: 'Parameter error 400',
forbidden: 'Access Forbidden 403',
serverErr: 'Server error 500',
resHtml: 'Response page',
allowHelper: 'Allowing access will skip subsequent WAF rules, please use with caution',
captcha: 'human-machine verification',
fiveSeconds: '5 seconds verification',
location: 'Region',
redisConfig: 'Redis configuration',
redisHelper: 'Enable Redis to persist temporarily blocked IPs',
wafHelper: 'All websites will lose protection after closing',
},
monitor: {
name: 'Website Monitor',
Expand Down
29 changes: 29 additions & 0 deletions frontend/src/lang/modules/tw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2094,6 +2094,35 @@ const message = {
javaFileter: 'Java 危險檔案過濾',
scannerFilter: '掃描器過濾',
escapeFilter: '轉義過濾',
customRule: '自訂規則',
httpMethod: 'HTTP 方法過濾',
fileExt: '檔案上傳限制',
fileExtHelper: '禁止上傳的檔案副檔名',
deny: '禁止',
allow: '只允許',
field: '匹配對象',
pattern: '符合條件',
ruleContent: '符合內容',
contain: '包含',
equal: '等於',
regex: '正規表示式',
notEqual: '不等於',
customRuleHelper: '根據條件匹配執行對應動作',
actionAllow: '允許',
blockIP: '封鎖 IP',
code: '返回狀態碼',
noRes: '斷開連線 444',
badReq: '參數錯誤 400',
forbidden: '禁止訪問 403',
serverErr: '伺服器錯誤 500',
resHtml: '回應頁面',
allowHelper: '允許訪問會跳過後續的 WAF 規則,請謹慎使用',
captcha: '人機驗證',
fiveSeconds: '5 秒驗證',
location: '地區',
redisConfig: 'Redis 配置',
redisHelper: '開啟 Redis 可以將暫時拉黑的 IP 持久化',
wafHelper: '關閉之後所有網站將失去防護',
},
monitor: {
name: '網站監控',
Expand Down
32 changes: 31 additions & 1 deletion frontend/src/lang/modules/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2011,6 +2011,7 @@ const message = {
},
xpack: {
name: '专业版',
menu: '高级功能',
waf: {
name: 'WAF',
blackWhite: '黑白名单',
Expand Down Expand Up @@ -2065,7 +2066,7 @@ const message = {
cookieHelper: '禁止请求中携带恶意 Cookie',
headerDefense: 'Header 规则',
headerHelper: '禁止请求中携带恶意 Header',
httpRule: 'HTTP 请求方法规则',
httpRule: 'HTTP 规则',
httpHelper: '限制网站的请求方法类型',
geoRule: '地区访问限制',
geoHelper: '限制某些地区访问你的网站',
Expand Down Expand Up @@ -2094,6 +2095,35 @@ const message = {
javaFileter: 'Java 危险文件过滤',
scannerFilter: '扫描器过滤',
escapeFilter: '转义过滤',
customRule: '自定义规则',
httpMethod: 'HTTP 方法过滤',
fileExt: '文件上传限制',
fileExtHelper: '禁止上传的文件扩展名',
deny: '禁止',
allow: '仅允许',
field: '匹配对象',
pattern: '匹配条件',
ruleContent: '匹配内容',
contain: '包含',
equal: '等于',
regex: '正则表达式',
notEqual: '不等于',
customRuleHelper: '根据条件匹配执行相应动作',
actionAllow: '允许',
blockIP: '封禁 IP',
code: '返回状态码',
noRes: '断开连接 444',
badReq: '参数错误 400',
forbidden: '禁止访问 403',
serverErr: '服务器错误 500',
resHtml: '响应页面',
allowHelper: '允许访问会跳过后续的 WAF 规则,请谨慎使用',
captcha: '人机验证',
fiveSeconds: '5 秒验证',
location: '地区',
redisConfig: 'Redis 配置',
redisHelper: '开启 Redis 可以将临时拉黑的 IP 持久化',
wafHelper: '关闭之后所有网站将失去防护',
},
monitor: {
name: '网站监控',
Expand Down
10 changes: 8 additions & 2 deletions frontend/src/views/website/runtime/node/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref } from 'vue';
import { Runtime } from '@/api/interface/runtime';
import { OperateRuntime, SearchRuntimes } from '@/api/modules/runtime';
import { OperateRuntime, SearchRuntimes, SyncRuntime } from '@/api/modules/runtime';
import { dateFormat } from '@/utils/util';
import OperateNode from '@/views/website/runtime/node/operate/index.vue';
import Status from '@/components/status/index.vue';
Expand Down Expand Up @@ -192,6 +192,10 @@ const search = async () => {
}
};

const sync = () => {
SyncRuntime();
};

const openModules = (row: Runtime.Runtime) => {
moduleRef.value.acceptParams({ id: row.id, packageManager: row.params['PACKAGE_MANAGER'] });
};
Expand Down Expand Up @@ -243,10 +247,12 @@ const toFolder = (folder: string) => {
};

onMounted(() => {
sync();
search();
timer = setInterval(() => {
search();
}, 10000 * 3);
sync();
}, 1000 * 10);
});

onUnmounted(() => {
Expand Down
Loading