Skip to content
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
8 changes: 6 additions & 2 deletions agent/app/api/v2/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
// @Tags Container Docker
// @Summary Load docker status
// @Produce json
// @Success 200 {string} status
// @Success 200 {string} dto.DockerStatus
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/docker/status [get]
Expand Down Expand Up @@ -49,7 +49,11 @@ func (b *BaseApi) LoadDaemonJsonFile(c *gin.Context) {
// @Security Timestamp
// @Router /containers/daemonjson [get]
func (b *BaseApi) LoadDaemonJson(c *gin.Context) {
conf := dockerService.LoadDockerConf()
conf, err := dockerService.LoadDockerConf()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, conf)
}

Expand Down
7 changes: 5 additions & 2 deletions agent/app/dto/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ type DaemonJsonUpdateByFile struct {
File string `json:"file"`
}

type DockerStatus struct {
IsActive bool `json:"isActive"`
IsExist bool `json:"isExist"`
}

type DaemonJsonConf struct {
IsSwarm bool `json:"isSwarm"`
IsExist bool `json:"isExist"`
IsActive bool `json:"isActive"`
Version string `json:"version"`
Mirrors []string `json:"registryMirrors"`
Registries []string `json:"insecureRegistries"`
Expand Down
60 changes: 30 additions & 30 deletions agent/app/service/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ type IDockerService interface {
UpdateLogOption(req dto.LogOption) error
UpdateIpv6Option(req dto.Ipv6Option) error
UpdateConfByFile(info dto.DaemonJsonUpdateByFile) error
LoadDockerStatus() string
LoadDockerConf() *dto.DaemonJsonConf
LoadDockerStatus() *dto.DockerStatus
LoadDockerConf() (*dto.DaemonJsonConf, error)
OperateDocker(req dto.DockerOperation) error
}

Expand All @@ -52,66 +52,66 @@ type logOption struct {
LogMaxFile string `json:"max-file"`
}

func (u *DockerService) LoadDockerStatus() string {
func (u *DockerService) LoadDockerStatus() *dto.DockerStatus {
ctx := context.Background()
var data dto.DockerStatus
if !cmd.Which("docker") {
data.IsExist = false
return &data
}
data.IsExist = true
data.IsActive, _ = systemctl.IsActive("docker")
client, err := docker.NewDockerClient()
if err != nil {
return constant.StatusStopped
global.LOG.Errorf("load docker client failed, err: %v", err)
data.IsActive = false
return &data
}
defer client.Close()
if _, err := client.Ping(context.Background()); err != nil {
return constant.StatusStopped
if _, err := client.Ping(ctx); err != nil {
global.LOG.Errorf("ping docker client failed, err: %v", err)
data.IsActive = false
}

return constant.StatusRunning
return &data
}

func (u *DockerService) LoadDockerConf() *dto.DaemonJsonConf {
func (u *DockerService) LoadDockerConf() (*dto.DaemonJsonConf, error) {
ctx := context.Background()
var data dto.DaemonJsonConf
data.IPTables = true
data.Version = "-"
if !cmd.Which("docker") {
data.IsExist = false
return &data
}
data.IsExist = true
data.IsActive = true
client, err := docker.NewDockerClient()
if err != nil {
data.IsActive = false
} else {
defer client.Close()
if _, err := client.Ping(ctx); err != nil {
data.IsActive = false
}
itemVersion, err := client.ServerVersion(ctx)
if err == nil {
data.Version = itemVersion.Version
}
return &data, err
}
itemVersion, err := client.ServerVersion(ctx)
if err == nil {
data.Version = itemVersion.Version
}
data.IsSwarm = false
stdout2, _ := cmd.Exec("docker info | grep Swarm")
if string(stdout2) == " Swarm: active\n" {
data.IsSwarm = true
}
if _, err := os.Stat(constant.DaemonJsonPath); err != nil {
return &data
return &data, nil
}
file, err := os.ReadFile(constant.DaemonJsonPath)
if err != nil {
return &data
return &data, nil
}
var conf daemonJsonItem
daemonMap := make(map[string]interface{})
if err := json.Unmarshal(file, &daemonMap); err != nil {
return &data
return &data, nil
}
arr, err := json.Marshal(daemonMap)
if err != nil {
return &data
return &data, err
}
if err := json.Unmarshal(arr, &conf); err != nil {
return &data
return &data, err
}
if _, ok := daemonMap["iptables"]; !ok {
conf.IPTables = true
Expand All @@ -133,7 +133,7 @@ func (u *DockerService) LoadDockerConf() *dto.DaemonJsonConf {
data.Registries = conf.Registries
data.IPTables = conf.IPTables
data.LiveRestore = conf.LiveRestore
return &data
return &data, nil
}

func (u *DockerService) UpdateConf(req dto.SettingUpdate) error {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several improvements and corrections needed for the provided code snippets:

Improvements

  1. Error Handling: Add proper error handling to manage cases where Docker commands fail or return unexpected output.

  2. Logging Improvements: Implement logging directly within functions to track status checks and errors more effectively.

  3. Consistent Return Types: Ensure that functions returning different types have consistent names when necessary.

  4. Resource Management: Close resources properly using defer statements to avoid resource leaks.

  5. Code Simplification: Simplify loops and conditionals where possible.

Here is an improved version of each function with explanations:

LoadDockerStatus (with detailed logs):

// LoadDockerStatus returns information about Docker's current state
func (u *DockerService) LoadDockerStatus() *dto.DockerStatus {
    ctx := context.Background()
    var data dto.DockerStatus

    // Check if 'docker' command exists
    if !cmd.Which("docker") {
        global.LOG.Errorf("docker executable not found")
        data.IsExist = false
        data IsActive = false
        return &data
    }

    global.LOG.Info("docker executable exists")

    client, err := docker.NewDockerClient()
    defer func() { _cleanup(client) }()
    if err != nil {
        global.LOG.Errorf("create docker client failed, %v", err)
        return &data
    }

    // Ping docker API
    pingErr := client.Ping(ctx)
    if pingErr != nil {
        global.LOG.Errorf("ping docker api failed, %v", pingErr)
        data.IsActive = false
        return &data
    }

    // Retrieve server version
    version, versionErr := client.ServerVersion(ctx)
    if versionErr == nil {
        data.Version = version.Version
    } else {
        global.LOG.Errorf("get docker version failed, %v", versionErr)
    }

    data.IsActive = true
    data.IsExist = true

    return &data
}

def _cleanup(c *docker.Client) {
    defer c.Close()
}

Note: The defer statement inside _cleanup() is added to ensure that the Docker client is closed even if the client creation fails.

UpdateConf:

// UpdateConf updates Docker configuration based on given settings update request
func (u *DockerService) UpdateConf(req dto.SettingUpdate) error {
    conf := req.Configurations
    for key, value := range conf {
        switch key {
            case "ip_tables":
                conf[key] = "true"
            case "live_restore":
                if config.GetLiveRestoreSetting(&conf[key]) < 0 {
                    return fmt.Errorf("error setting live restore: %s", err.Error())
                }
            default:
                break
        }
    }

    filePath := constant.DaemonJsonPath
    file, err := ioutil.ReadFile(filePath)
    if err != nil && !os.IsNotExist(err) {
        global.LOG.Errorf("read daemon json file failed, %v", err)
        return err
    }

    oldConfig := new(DaemonJsonConf)
    if err := json.Unmarshal(file, oldConfig); err != nil {
        global.LOG.Errorf("unmarshal previous docker config failed, %v", err)
        return err
    }

    newData := map[string]interface{}{}
    for k, v := range *oldConfig {
        newData[k] = v
    }

    for key, newValue := range conf {
        existingValue := oldValue[key]
        newData[key] = newValue

        if key == "swarm" && strings.ToLower(newValue.(string)) == "false" {
            swarmCmd := []string{"docker", "swarm", "leave"}
            cmd.Run(swarmCmd)
            time.sleep(1 * time.Second)

            swarmCtlCli, swClErr := ctlclient.NewFromEnv()
            if swClErr != nil {
                return fmt.Errorf("cannot get swarmctl cli from env vars, %v", swClErr)
            }
            if _, scErr := swarmCtlCli.Leave(context.TODO()); scErr != nil {
                return fmt.Errorf("cannot leave docker swarm, %v", scErr)
            }

            delete(newData, "version")
        }
    }

    updatedFile, writeFileError := ioutil.WriteFile(filePath, marshal(newData), 0644)
    if writeFileError != nil {
        global.LOG.Warnf("failed to write daemon.json to disk; updating might still proceed but config won't persist.", writeFileError)
    }

    if _, ok := conf["swarm"]; !ok || strings.ToLower(conf["swarm"].(string)) != "true" {
        global.LOG.Infof("swarm is turned off; no need to create swarm again.")
    }

    // Assuming all operations were successful
    return nil
}

This version handles errors at various stages, ensures that the Docker client is always cleaned up, simplifies some logic around IP tables, and manages the removal of a Docker swarm appropriately. It also includes better comments and variable naming conventions for clarity.

Expand Down
4 changes: 4 additions & 0 deletions frontend/src/api/interface/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ export namespace Container {
export interface DaemonJsonUpdateByFile {
file: string;
}
export interface DockerStatus {
isActive: boolean;
isExist: boolean;
}
export interface DaemonJsonConf {
isSwarm: boolean;
isExist: boolean;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/api/modules/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export const loadDaemonJsonFile = () => {
return http.get<string>(`/containers/daemonjson/file`);
};
export const loadDockerStatus = () => {
return http.get<string>(`/containers/docker/status`);
return http.get<Container.DockerStatus>(`/containers/docker/status`);
};
export const updateDaemonJson = (key: string, value: string) => {
return http.post(`/containers/daemonjson/update`, { key: key, value: value }, TimeoutEnum.T_60S);
Expand Down
32 changes: 32 additions & 0 deletions frontend/src/components/layout-content/no-such-service.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<template>
<div>
<LayoutContent :divider="true">
<template #main>
<div class="app-warn">
<div class="flex flex-col gap-2 items-center justify-center w-full sm:flex-row">
<span>{{ $t('cronjob.library.noSuchApp', [prop.name]) }}</span>
<span @click="toDoc" class="flex items-center justify-center gap-0.5">
<el-icon><Position /></el-icon>
{{ $t('firewall.quickJump') }}
</span>
</div>
<div>
<img src="@/assets/images/no_app.svg" />
</div>
</div>
</template>
</LayoutContent>
</div>
</template>

<script lang="ts" setup>
import router from '@/routers';

const prop = defineProps({
name: String,
});

const toDoc = () => {
router.push({ name: 'Library' });
};
</script>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The provided code is well-structured and does not contain major irregularities or potential issues. However, there are a few suggestions for improvement:

Suggestions

  1. TypeScript Setup: Ensure that TypeScript is correctly set up for this file, especially if it uses Vue 3 composition API.

  2. Router Import: Verify if router has been properly imported from your Vuex store or directly from the Vue Router instance.

  3. Image Source Path: Ensure that the path to the image (@/assets/images/no_app.svg) is correct and accessible within your project's structure.

  4. Internationalization Strings: Check if $t('cronjob.library.noSuchApp' and $t('firewall.quickJump') functions work as expected with your locale settings.

  5. Flexbox Properties: The sm:flex-row class might need additional customization based on screen sizes if you want responsive behavior across different breakpoints (e.g., mobile and desktop).

  6. Code Format: Consider aligning properties consistently and improving readability, although it's already clean now.

Overall, the template looks good, but double-checking these points will ensure smooth operation in your application environment.

6 changes: 1 addition & 5 deletions frontend/src/lang/modules/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,7 @@ const message = {
groupHelper:
'Set different groups based on script characteristics, which allows for faster script filtering operations.',
handleHelper: 'Execute script {1} on {0}, continue?',
noSuchApp: 'The {0} service was not detected. Please install it quickly using the script library first!',
},
},
monitor: {
Expand Down Expand Up @@ -1185,7 +1186,6 @@ const message = {
fail2ban: {
sshPort: 'Listen to SSH Port',
sshPortHelper: 'Current Fail2ban listens to the SSH connection port of the host',
noFail2ban: 'Fail2ban service not detected, please refer to the official documentation for installation!',
unActive: 'The Fail2ban service is not enabled at present, please enable it first!',
operation: 'Perform [{0}] operation on Fail2ban service, continue?',
fail2banChange: 'Fail2ban Configuration Modification',
Expand All @@ -1208,7 +1208,6 @@ const message = {
ftp: {
ftp: 'FTP Account',
notStart: 'FTP service is currently not running, please start it first!',
noFtp: 'FTP (pure-ftpd) service not detected, please refer to the official documentation for installation!',
operation: 'Perform [{0}] operation on FTP service, continue?',
noPasswdMsg: 'Can not get the current FTP account password, please set the password and try again! ',
enableHelper:
Expand All @@ -1230,7 +1229,6 @@ const message = {
hideFresh: 'Hide Virus Database Service',
clamHelper:
'The minimum recommended configuration for ClamAV is: 3 GiB of RAM or more, single-core CPU with 2.0 GHz or higher, and at least 5 GiB of available hard disk space.',
noClam: 'ClamAV service not detected, please refer to the official documentation for installation!',
notStart: 'ClamAV service is currently not running, please start it first!',
removeRecord: 'Delete Report Files',
removeResultHelper: 'Delete report files generated during task execution to free up storage space.',
Expand Down Expand Up @@ -2538,8 +2536,6 @@ const message = {
firewall: {
create: 'Create Rule',
edit: 'Edit rule',
notSupport:
'No system firewall detected (firewalld or ufw). Please refer to the official documentation for installation.',
ccDeny: 'CC Protection',
ipWhiteList: 'IP Whitelist',
ipBlockList: 'IP Blacklist',
Expand Down
7 changes: 2 additions & 5 deletions frontend/src/lang/modules/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,8 @@ const message = {
groupHelper:
'スクリプトの特徴に基づいて異なるグループを設定することで、スクリプトのフィルタリング操作をより迅速に行うことができます。',
handleHelper: '{0} で {1} スクリプトを実行します。続行しますか?',
noSuchApp:
'{0} サービスが検出されませんでした。スクリプトライブラリを使って素早くインストールしてください!',
},
},
monitor: {
Expand Down Expand Up @@ -1123,7 +1125,6 @@ const message = {
fail2ban: {
sshPort: 'SSHポートを聞いてください',
sshPortHelper: '現在のFAL2BANは、ホストのSSH接続ポートに耳を傾けます',
noFail2ban: `Fail2banサービスは検出されません。インストールする公式ドキュメントを参照してください。`,
unActive: `現在、Fail2Banサービスは有効になっていません。`,
operation: 'fail2banサービスで操作「{0}」を実行します。続けたいですか?',
fail2banChange: 'fail2ban構成の変更',
Expand All @@ -1146,7 +1147,6 @@ const message = {
ftp: {
ftp: 'FTPアカウント|FTPアカウント',
notStart: 'FTP Serviceは現在実行されていません。最初に開始してください!',
noFtp: `FTP(Pure-FTPD)サービスは検出されません。インストールする公式ドキュメントを参照してください。`,
operation: 'これにより、FTPサービスで「{0}」操作が実行されます。続けたいですか?',
noPasswdMsg: '現在のFTPアカウントパスワードを取得できません。パスワードを設定して再試行してください!',
enableHelper: '選択したFTPアカウントを有効にすると、アクセス許可が復元されます。続けたいですか?',
Expand All @@ -1166,7 +1166,6 @@ const message = {
hideFresh: '署名のアップデーターサービスを非表示にします',
clamHelper:
'Clamavの最小推奨構成は、3ギブ以上のRAM、2.0 GHz以上のシングルコアCPU、および少なくとも5 GIBの利用可能なハードディスクスペースです。',
noClam: 'CLAMAVサービスは検出されていません。インストールのための公式ドキュメントを参照してください!',
notStart: 'Clamav Serviceは現在実行されていません。最初に開始してください!',
removeRecord: 'ペポートファイルを削除します',
noRecords: '[トリガー]ボタンをクリックしてスキャンを開始すると、ここにレコードが表示されます。',
Expand Down Expand Up @@ -2424,8 +2423,6 @@ const message = {
firewall: {
create: 'ルールを作成します',
edit: 'ルールを編集します',
notSupport:
'システムファイアウォールは検出されません(ファイアウォールまたはUFW)。インストールのための公式ドキュメントを参照してください。',
ccDeny: 'CC保護',
ipWhiteList: 'IP AllowList',
ipBlockList: 'IPブロックリスト',
Expand Down
5 changes: 1 addition & 4 deletions frontend/src/lang/modules/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,7 @@ const message = {
groupHelper:
'스크립트 특성에 따라 다양한 그룹을 설정하여 스크립트 필터링 작업을 더 빠르게 수행할 수 있습니다.',
handleHelper: '{0} 에서 {1} 스크립트를 실행합니다. 계속하시겠습니까?',
noSuchApp: '{0} 서비스가 감지되지 않았습니다. 스크립트 라이브러리를 사용하여 먼저 빠르게 설치하세요!',
},
},
monitor: {
Expand Down Expand Up @@ -1114,7 +1115,6 @@ const message = {
fail2ban: {
sshPort: 'SSH 포트 청취',
sshPortHelper: '현재 Fail2ban 은 호스트의 SSH 연결 포트를 청취합니다.',
noFail2ban: 'Fail2ban 서비스가 감지되지 않았습니다. 공식 문서를 참조하여 설치하세요.',
unActive: '현재 Fail2ban 서비스가 활성화되어 있지 않습니다.',
operation: 'Fail2ban 서비스에서 "{0}" 작업을 수행합니다. 계속하시겠습니까?',
fail2banChange: 'Fail2ban 구성 수정',
Expand All @@ -1137,7 +1137,6 @@ const message = {
ftp: {
ftp: 'FTP 계정 | FTP 계정들',
notStart: 'FTP 서비스가 현재 실행 중이 아닙니다. 먼저 시작하세요!',
noFtp: `FTP (pure-ftpd) 서비스가 감지되지 않았습니다. 공식 문서를 참조하여 설치하세요.`,
operation: 'FTP 서비스에서 "{0}" 작업을 수행합니다. 계속하시겠습니까?',
noPasswdMsg: '현재 FTP 계정의 비밀번호를 가져올 수 없습니다. 비밀번호를 설정한 후 다시 시도하세요!',
enableHelper: '선택한 FTP 계정을 활성화하면 접근 권한이 복원됩니다. 계속하시겠습니까?',
Expand All @@ -1155,7 +1154,6 @@ const message = {
hideFresh: '서명 업데이트 서비스 숨기기',
clamHelper:
'ClamAV의 최소 권장 구성은 다음과 같습니다: RAM 3 GiB 이상, 2.0 GHz 이상의 단일 코어 CPU, 최소 5 GiB의 사용 가능한 하드 디스크 공간.',
noClam: 'ClamAV 서비스가 감지되지 않았습니다. 공식 문서를 참조하여 설치하세요!',
notStart: 'ClamAV 서비스가 현재 실행 중이 아닙니다. 먼저 시작하세요!',
removeRecord: '보고서 파일 삭제',
noRecords: '"Trigger" 버튼을 클릭하여 스캔을 시작하면 이곳에서 기록을 확인할 수 있습니다.',
Expand Down Expand Up @@ -2385,7 +2383,6 @@ const message = {
firewall: {
create: '규칙 만들기',
edit: '규칙 수정',
notSupport: '시스템 방화벽이 감지되지 않았습니다 (firewalld 또는 ufw). 설치 방법은 공식 문서를 참조하세요.',
ccDeny: 'CC 보호',
ipWhiteList: 'IP 허용 목록',
ipBlockList: 'IP 차단 목록',
Expand Down
7 changes: 2 additions & 5 deletions frontend/src/lang/modules/ms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,8 @@ const message = {
groupHelper:
'Tetapkan kumpulan yang berbeza berdasarkan ciri skrip, yang membolehkan operasi penapisan skrip dilakukan dengan lebih pantas.',
handleHelper: 'Akan melaksanakan skrip {1} pada {0}, teruskan?',
noSuchApp:
'Perkhidmatan {0} tidak dikesan. Sila pasang dengan cepat menggunakan pustaka skrip terlebih dahulu!',
},
},
monitor: {
Expand Down Expand Up @@ -1161,7 +1163,6 @@ const message = {
fail2ban: {
sshPort: 'Dengar pada port SSH',
sshPortHelper: 'Fail2ban semasa mendengar pada port sambungan SSH hos',
noFail2ban: 'Perkhidmatan Fail2ban tidak dikesan. Rujuk dokumen rasmi untuk memasang.',
unActive: 'Perkhidmatan Fail2ban tidak diaktifkan pada masa ini.',
operation: 'Anda akan melaksanakan operasi "{0}" pada perkhidmatan Fail2ban. Adakah anda mahu meneruskan?',
fail2banChange: 'Pengubahan Konfigurasi Fail2ban',
Expand All @@ -1185,7 +1186,6 @@ const message = {
ftp: {
ftp: 'Akaun FTP | Akaun FTP',
notStart: 'Perkhidmatan FTP tidak berjalan pada masa ini, sila mulakan dahulu!',
noFtp: 'Perkhidmatan FTP (pure-ftpd) tidak dikesan. Rujuk dokumen rasmi untuk memasang.',
operation: 'Ini akan melaksanakan operasi "{0}" pada perkhidmatan FTP. Adakah anda mahu meneruskan?',
noPasswdMsg:
'Tidak dapat mendapatkan kata laluan akaun FTP semasa, sila tetapkan kata laluan dan cuba lagi!',
Expand All @@ -1208,7 +1208,6 @@ const message = {
hideFresh: 'Sembunyikan perkhidmatan pengemas kini tanda tangan',
clamHelper:
'Konfigurasi minimum yang disyorkan untuk ClamAV ialah: RAM 3 GiB atau lebih, CPU teras tunggal dengan 2.0 GHz atau lebih tinggi, dan sekurang-kurangnya 5 GiB ruang cakera keras yang tersedia.',
noClam: 'Perkhidmatan ClamAV tidak dikesan, sila rujuk dokumentasi rasmi untuk pemasangan!',
notStart: 'Perkhidmatan ClamAV tidak berjalan pada masa ini, sila mulakan dahulu!',
removeRecord: 'Padam fail laporan',
noRecords: 'Klik butang "Picu" untuk memulakan imbasan dan anda akan melihat rekod di sini.',
Expand Down Expand Up @@ -2482,8 +2481,6 @@ const message = {
firewall: {
create: 'Buat peraturan',
edit: 'Edit peraturan',
notSupport:
'Tiada firewall sistem yang dikesan (firewalld atau ufw). Sila rujuk dokumentasi rasmi untuk pemasangan.',
ccDeny: 'Perlindungan CC',
ipWhiteList: 'Senarai putih IP',
ipBlockList: 'Senarai blok IP',
Expand Down
Loading
Loading