@@ -25,6 +25,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@types/express": "^4.17.0",
 | 
			
		||||
        "@types/mongodb": "^3.3.13",
 | 
			
		||||
        "@types/socket.io": "^2.1.2",
 | 
			
		||||
        "nodemon": "^1.19.1",
 | 
			
		||||
        "rimraf": "^2.6.3",
 | 
			
		||||
@@ -32,7 +33,7 @@
 | 
			
		||||
        "typescript": "^3.5.2"
 | 
			
		||||
    },
 | 
			
		||||
    "nodemonConfig": {
 | 
			
		||||
        "verbose": true,
 | 
			
		||||
        "verbose": false,
 | 
			
		||||
        "ignore": [
 | 
			
		||||
            ".git",
 | 
			
		||||
            "public"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								packages/core/public/editor/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								packages/core/public/editor/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="zh">
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
	<meta charset="UTF-8">
 | 
			
		||||
	<title>编辑器</title>
 | 
			
		||||
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 | 
			
		||||
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
 | 
			
		||||
	<meta http-equiv="X-UA-Compatible" content="IE=Edge">
 | 
			
		||||
	<link rel="stylesheet" href="https://houtai.baidu.com/v2/csssdk">
 | 
			
		||||
	<style>
 | 
			
		||||
		html,
 | 
			
		||||
		body,
 | 
			
		||||
		.app-wrapper {
 | 
			
		||||
			position: relative;
 | 
			
		||||
			width: 100%;
 | 
			
		||||
			height: 100%;
 | 
			
		||||
			margin: 0;
 | 
			
		||||
			padding: 0;
 | 
			
		||||
		}
 | 
			
		||||
	</style>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
	<div id="root" class="app-wrapper"></div>
 | 
			
		||||
	<script src="https://houtai.baidu.com/v2/jssdk"></script>
 | 
			
		||||
	<script src="index.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										51
									
								
								packages/core/public/editor/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								packages/core/public/editor/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
(async function() {
 | 
			
		||||
    var amis = amisRequire('amis/embed');
 | 
			
		||||
    amis.embed('#root', {
 | 
			
		||||
        definitions: {
 | 
			
		||||
            "editor-page": {
 | 
			
		||||
                "position": "right",
 | 
			
		||||
                "resizable": true,
 | 
			
		||||
                "title": `<% if (data.name) { print('页面 '+data.name+' 详情') } else { print ('新增页面') } %>`,
 | 
			
		||||
                "size": "lg",
 | 
			
		||||
                "body": {
 | 
			
		||||
                    "type": "form",
 | 
			
		||||
                    "submitText": '',
 | 
			
		||||
                    "title": "",
 | 
			
		||||
                    "controls": [
 | 
			
		||||
                        {
 | 
			
		||||
                            "name": "name",
 | 
			
		||||
                            "type": "text",
 | 
			
		||||
                        },
 | 
			
		||||
                        {
 | 
			
		||||
                            "name": "content",
 | 
			
		||||
                            "type": "editor",
 | 
			
		||||
                            "language": "json",
 | 
			
		||||
                            "editorTheme": "vs-dark",
 | 
			
		||||
                            "height": "800",
 | 
			
		||||
                            "label": false
 | 
			
		||||
                        },
 | 
			
		||||
                        {
 | 
			
		||||
                            "type": "button",
 | 
			
		||||
                            "label": "保存",
 | 
			
		||||
                            "actionType": "ajax",
 | 
			
		||||
                            "api": {
 | 
			
		||||
                                "url": "/page/manager/${_id}",
 | 
			
		||||
                                "data": {
 | 
			
		||||
                                    "name": "${name}",
 | 
			
		||||
                                    "content": "${content}"
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        type: 'page',
 | 
			
		||||
        title: '页面管理',
 | 
			
		||||
        body: {
 | 
			
		||||
            name: "editor",
 | 
			
		||||
            type: "service",
 | 
			
		||||
            schemaApi: "get:/page/manager/editor"
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
})();
 | 
			
		||||
							
								
								
									
										28
									
								
								packages/core/public/event/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								packages/core/public/event/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
	<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2.2.0/dist/socket.io.js"> </script>
 | 
			
		||||
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/xterm.css" />
 | 
			
		||||
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/fullscreen/fullscreen.css">
 | 
			
		||||
 | 
			
		||||
	<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/xterm.js"></script>
 | 
			
		||||
	<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/fit/fit.js"></script>
 | 
			
		||||
	<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/attach/attach.js"></script>
 | 
			
		||||
	<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/fullscreen/fullscreen.js"></script>
 | 
			
		||||
	<style>
 | 
			
		||||
		#terminal-container .terminal.xterm {
 | 
			
		||||
			height: 100%;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		#terminal-container .xterm-viewport {
 | 
			
		||||
			height: 100% !important;
 | 
			
		||||
		}
 | 
			
		||||
	</style>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
	<div id="terminal" style="height: 100%;"></div>
 | 
			
		||||
	<script type="text/javascript" src="js/index.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
@@ -1,28 +1,30 @@
 | 
			
		||||
<html>
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="zh">
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
	<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2.2.0/dist/socket.io.js"> </script>
 | 
			
		||||
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/xterm.css" />
 | 
			
		||||
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/fullscreen/fullscreen.css">
 | 
			
		||||
 | 
			
		||||
	<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/xterm.js"></script>
 | 
			
		||||
	<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/fit/fit.js"></script>
 | 
			
		||||
	<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/attach/attach.js"></script>
 | 
			
		||||
	<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/fullscreen/fullscreen.js"></script>
 | 
			
		||||
	<meta charset="UTF-8">
 | 
			
		||||
	<title>四喜服务部署平台</title>
 | 
			
		||||
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 | 
			
		||||
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
 | 
			
		||||
	<meta http-equiv="X-UA-Compatible" content="IE=Edge">
 | 
			
		||||
	<link rel="stylesheet" href="https://houtai.baidu.com/v2/csssdk">
 | 
			
		||||
	<style>
 | 
			
		||||
		#terminal-container .terminal.xterm {
 | 
			
		||||
		html,
 | 
			
		||||
		body,
 | 
			
		||||
		.app-wrapper {
 | 
			
		||||
			position: relative;
 | 
			
		||||
			width: 100%;
 | 
			
		||||
			height: 100%;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		#terminal-container .xterm-viewport {
 | 
			
		||||
			height: 100% !important;
 | 
			
		||||
			margin: 0;
 | 
			
		||||
			padding: 0;
 | 
			
		||||
		}
 | 
			
		||||
	</style>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
	<div id="terminal" style="height: 100%;"></div>
 | 
			
		||||
	<script type="text/javascript" src="js/index.js"></script>
 | 
			
		||||
	<div id="root" class="app-wrapper"></div>
 | 
			
		||||
	<script src="https://houtai.baidu.com/v2/jssdk"></script>
 | 
			
		||||
	<script src="index.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										8
									
								
								packages/core/public/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								packages/core/public/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
(async function() {
 | 
			
		||||
    var amis = amisRequire('amis/embed');
 | 
			
		||||
    let page = window.location.hash.substring(1);
 | 
			
		||||
    amis.embed('#root', {
 | 
			
		||||
        type: "service",
 | 
			
		||||
        schemaApi: "get:/page/manager/" + page
 | 
			
		||||
    });
 | 
			
		||||
})();
 | 
			
		||||
							
								
								
									
										1
									
								
								packages/core/resources/docker.http
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								packages/core/resources/docker.http
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
POST https://dayu-api.miaowoo.cc/service/swirl_swirl/restart
 | 
			
		||||
							
								
								
									
										21
									
								
								packages/core/src/controller/docker/node.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								packages/core/src/controller/docker/node.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
import { controller, httpGet, httpPost } from 'inversify-express-utils';
 | 
			
		||||
import * as docker from '@dayu/docker-api'
 | 
			
		||||
 | 
			
		||||
@controller('/node')
 | 
			
		||||
class NodeController {
 | 
			
		||||
    @httpGet('/list')
 | 
			
		||||
    public async list() {
 | 
			
		||||
        let nodes = await docker.node.list();
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            data: nodes.map(n => ({
 | 
			
		||||
                id: n.ID,
 | 
			
		||||
                manager: n.ManagerStatus,
 | 
			
		||||
                hostname: n.Description.Hostname,
 | 
			
		||||
                version: n.Description.Engine.EngineVersion,
 | 
			
		||||
                status: n.Status,
 | 
			
		||||
                raw: JSON.stringify(n)
 | 
			
		||||
            }))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										75
									
								
								packages/core/src/controller/docker/service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								packages/core/src/controller/docker/service.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
import { controller, post, get, requestParam, queryParam } from '@cc-server/binding';
 | 
			
		||||
import * as docker from '@dayu/docker-api'
 | 
			
		||||
 | 
			
		||||
@controller('/service')
 | 
			
		||||
class ServiceController {
 | 
			
		||||
    @get('/list')
 | 
			
		||||
    public async list(@queryParam('page') page: number, @queryParam('perPage') perPage: number, ) {
 | 
			
		||||
        let services = await docker.service.list();
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            msg: '',
 | 
			
		||||
            data: services.map(s => ({
 | 
			
		||||
                "service-name": s.Spec.Name,
 | 
			
		||||
                image: s.Spec.TaskTemplate.ContainerSpec.Image.split('@')[0],
 | 
			
		||||
                updated_at: s.UpdatedAt,
 | 
			
		||||
                mode: s.Spec.Mode,
 | 
			
		||||
                update_status: s.UpdateStatus
 | 
			
		||||
            }))
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @post('/:id/restart')
 | 
			
		||||
    public async restart(@requestParam("id") id: string) {
 | 
			
		||||
        let service = await docker.service.inspect(id);
 | 
			
		||||
        service.Spec.TaskTemplate.ForceUpdate++
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            msg: '重启指令已发送',
 | 
			
		||||
            data: docker.service.update(id, { version: service.Version.Index }, service.Spec)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @post('/:id/rollback')
 | 
			
		||||
    public async rollback(@requestParam("id") id: string) {
 | 
			
		||||
        let service = await docker.service.inspect(id);
 | 
			
		||||
        if (!service.PreviousSpec) {
 | 
			
		||||
            return {
 | 
			
		||||
                status: 1,
 | 
			
		||||
                msg: '服务自启动后从未重启<br>无法回滚!'
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            msg: '回滚指令已发送',
 | 
			
		||||
            data: docker.service.update(id, { version: service.Version.Index, rollback: 'previous' }, service.Spec)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @post('/delete')
 | 
			
		||||
    public async delete() {
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            msg: '删除成功!',
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @get('/:id')
 | 
			
		||||
    public async details(@requestParam('id') id: string) {
 | 
			
		||||
        let service = await docker.service.inspect(id);
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            data: {
 | 
			
		||||
                id: service.ID,
 | 
			
		||||
                name: service.Spec.Name,
 | 
			
		||||
                env: (service.Spec.TaskTemplate.ContainerSpec.Env ?? []).map(e => {
 | 
			
		||||
                    let args = e.split('=');
 | 
			
		||||
                    return { key: args[0], value: args[1] }
 | 
			
		||||
                }),
 | 
			
		||||
                networks: service.Spec.TaskTemplate.Networks ?? [],
 | 
			
		||||
                raw: JSON.stringify(service)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,11 +1,11 @@
 | 
			
		||||
import { controller, httpGet, httpPost, requestParam } from 'inversify-express-utils';
 | 
			
		||||
import { controller, get, post, requestParam } from '@cc-server/binding';
 | 
			
		||||
import * as docker from '@dayu/docker-api'
 | 
			
		||||
 | 
			
		||||
const STACK_LABEL = 'com.docker.stack.namespace';
 | 
			
		||||
 | 
			
		||||
@controller('/stack')
 | 
			
		||||
class StackController {
 | 
			
		||||
    @httpGet('/list')
 | 
			
		||||
    @get('/list')
 | 
			
		||||
    public async list(): Promise<any> {
 | 
			
		||||
        let stacks: { [key: string]: string[] } = {};
 | 
			
		||||
        let result = [];
 | 
			
		||||
@@ -24,10 +24,13 @@ class StackController {
 | 
			
		||||
                stack.push(service.Spec.Name);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            data: result
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @httpGet('/:stack')
 | 
			
		||||
    @get('/:stack')
 | 
			
		||||
    public async details(@requestParam('stack') stack: string) {
 | 
			
		||||
        let filter: any = {}
 | 
			
		||||
        filter[`${STACK_LABEL}=${stack}`] = true
 | 
			
		||||
							
								
								
									
										21
									
								
								packages/core/src/controller/docker/task.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								packages/core/src/controller/docker/task.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
import { controller, post, get, requestParam, queryParam } from '@cc-server/binding';
 | 
			
		||||
import * as docker from '@dayu/docker-api'
 | 
			
		||||
 | 
			
		||||
@controller('/task')
 | 
			
		||||
class TaskController {
 | 
			
		||||
    @get('/list')
 | 
			
		||||
    public async list(@queryParam('page') page: number, @queryParam('perPage') perPage: number, ) {
 | 
			
		||||
        let tasks = await docker.task.list();
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            msg: '',
 | 
			
		||||
            data: tasks.map(s => ({
 | 
			
		||||
                id: s.ID,
 | 
			
		||||
                image: s.Spec.ContainerSpec.Image.split('@')[0],
 | 
			
		||||
                status: s.Status,
 | 
			
		||||
                updated_at: s.UpdatedAt,
 | 
			
		||||
                raw: JSON.stringify(s),
 | 
			
		||||
            }))
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								packages/core/src/controller/ext/group.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								packages/core/src/controller/ext/group.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
import { controller, get, post, requestParam } from '@cc-server/binding';
 | 
			
		||||
import * as docker from '@dayu/docker-api'
 | 
			
		||||
 | 
			
		||||
const GROUP_LABEL = 'pw.yumc.group.name'
 | 
			
		||||
 | 
			
		||||
@controller('/group')
 | 
			
		||||
class GroupController {
 | 
			
		||||
    @get('/list')
 | 
			
		||||
    public async list(): Promise<any> {
 | 
			
		||||
        let stacks: { [key: string]: string[] } = {};
 | 
			
		||||
        let result = [];
 | 
			
		||||
        let services = await docker.service.list();
 | 
			
		||||
        for (const service of services) {
 | 
			
		||||
            let stackName = service.Spec.Labels[GROUP_LABEL]
 | 
			
		||||
            if (stackName) {
 | 
			
		||||
                let stack = stacks[stackName];
 | 
			
		||||
                if (!stack) {
 | 
			
		||||
                    result.push({
 | 
			
		||||
                        name: stackName,
 | 
			
		||||
                        services: stack = []
 | 
			
		||||
                    })
 | 
			
		||||
                    stacks[stackName] = stack;
 | 
			
		||||
                }
 | 
			
		||||
                stack.push(service.Spec.Name);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @get('/:name')
 | 
			
		||||
    public async details(@requestParam('name') stack: string) {
 | 
			
		||||
        let filter: any = {}
 | 
			
		||||
        filter[`${GROUP_LABEL}=${stack}`] = true
 | 
			
		||||
        let filterOpt = {
 | 
			
		||||
            filters: JSON.stringify({
 | 
			
		||||
                "label": filter
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
        let services = await docker.service.list(filterOpt)
 | 
			
		||||
        let networks = await docker.network.list(filterOpt)
 | 
			
		||||
        return {
 | 
			
		||||
            services: services.map(service => service.Spec.Name),
 | 
			
		||||
            networks: networks.map(network => network.Name),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
import { controller, httpGet, httpPost } from 'inversify-express-utils';
 | 
			
		||||
import * as docker from '@dayu/docker-api'
 | 
			
		||||
 | 
			
		||||
@controller('/node')
 | 
			
		||||
class NodeController {
 | 
			
		||||
    @httpGet('/list')
 | 
			
		||||
    public async list() {
 | 
			
		||||
        return await docker.node.list();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										79
									
								
								packages/core/src/controller/page/dashboard.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								packages/core/src/controller/page/dashboard.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
import { controller, get, post } from "@cc-server/binding";
 | 
			
		||||
 | 
			
		||||
@controller('/page')
 | 
			
		||||
class PageDashboardController {
 | 
			
		||||
    @get('')
 | 
			
		||||
    async page() {
 | 
			
		||||
        return {
 | 
			
		||||
            type: 'page',
 | 
			
		||||
            title: '大禹容器管理',
 | 
			
		||||
            body: [{
 | 
			
		||||
                type: "button",
 | 
			
		||||
                label: "刷新页面",
 | 
			
		||||
                level: "dark",
 | 
			
		||||
                actionType: "reload",
 | 
			
		||||
                target: "editor"
 | 
			
		||||
            }, {
 | 
			
		||||
                type: 'divider'
 | 
			
		||||
            }, {
 | 
			
		||||
                "name": "editor",
 | 
			
		||||
                "type": "service",
 | 
			
		||||
                "className": "m-t",
 | 
			
		||||
                "schemaApi": "/page/editor"
 | 
			
		||||
            }]
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    @post('/editor')
 | 
			
		||||
    async editor() {
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            msg: '',
 | 
			
		||||
            data: {
 | 
			
		||||
                "type": "form",
 | 
			
		||||
                "initApi": "post:/page/service/list",
 | 
			
		||||
                "title": "",
 | 
			
		||||
                "controls": [{
 | 
			
		||||
                    "name": "api",
 | 
			
		||||
                    "type": "editor",
 | 
			
		||||
                    "language": "json",
 | 
			
		||||
                    "label": "JSON",
 | 
			
		||||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    @post('/dashboard')
 | 
			
		||||
    async dashboard() {
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            msg: '',
 | 
			
		||||
            data: {
 | 
			
		||||
                "type": "form",
 | 
			
		||||
                "api": "https://houtai.baidu.com/api/form/saveForm?waitSeconds=2",
 | 
			
		||||
                "title": "常规模式",
 | 
			
		||||
                "mode": "normal",
 | 
			
		||||
                "controls": [{
 | 
			
		||||
                    "type": "email",
 | 
			
		||||
                    "name": "email",
 | 
			
		||||
                    "required": true,
 | 
			
		||||
                    "placeholder": "请输入邮箱",
 | 
			
		||||
                    "label": "邮箱"
 | 
			
		||||
                }, {
 | 
			
		||||
                    "type":
 | 
			
		||||
                        "password",
 | 
			
		||||
                    "name": "password",
 | 
			
		||||
                    "label": "密码",
 | 
			
		||||
                    "required": true,
 | 
			
		||||
                    "placeholder": "请输入密码"
 | 
			
		||||
                }, {
 | 
			
		||||
                    "type": "checkbox",
 | 
			
		||||
                    "name": "rememberMe",
 | 
			
		||||
                    "label": "记住登录"
 | 
			
		||||
                }, {
 | 
			
		||||
                    "type": "submit",
 | 
			
		||||
                    "btnClassName": "btn-default",
 | 
			
		||||
                    "label": "登录"
 | 
			
		||||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										58
									
								
								packages/core/src/controller/page/manager.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								packages/core/src/controller/page/manager.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
import { DBClient } from '@cc-server/db'
 | 
			
		||||
import { controller, get, post, httpDelete, requestParam, requestBody, BaseHttpController } from "@cc-server/binding";
 | 
			
		||||
import { inject, named } from '@cc-server/ioc'
 | 
			
		||||
 | 
			
		||||
class Page {
 | 
			
		||||
    _id: string;
 | 
			
		||||
    name: string;
 | 
			
		||||
    content: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@controller('/page/manager')
 | 
			
		||||
class PageManagerController extends BaseHttpController {
 | 
			
		||||
    @inject(DBClient)
 | 
			
		||||
    @named('page')
 | 
			
		||||
    private client: DBClient<Page>
 | 
			
		||||
 | 
			
		||||
    @get('/list')
 | 
			
		||||
    async list() {
 | 
			
		||||
        let pages = await this.client.find({})
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            data: pages
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @get('/:name')
 | 
			
		||||
    async index(@requestParam('name') name: string) {
 | 
			
		||||
        let page = await this.client.findOne({ name })
 | 
			
		||||
        if (!page) {
 | 
			
		||||
            return {
 | 
			
		||||
                status: 404,
 | 
			
		||||
                msg: `未找到 ${name} 的页面配置数据!`
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return {
 | 
			
		||||
            status: 0,
 | 
			
		||||
            data: JSON.parse(page.content)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @post('/')
 | 
			
		||||
    async add(@requestBody() page: Page) {
 | 
			
		||||
        let result = this.client.insertOne(page);
 | 
			
		||||
        return { status: result ? 0 : 1, msg: result ? '插入 ' + page.name + ' 成功!' : '插入 ' + page.name + ' 失败!' };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @post('/:id')
 | 
			
		||||
    async update(@requestParam('id') _id: string, @requestBody() page: Page) {
 | 
			
		||||
        let result = this.client.updateById(_id, page)
 | 
			
		||||
        return { status: result ? 0 : 1, msg: result ? '更新 ' + page.name + ' 成功!' : '更新 ' + page.name + ' 失败!' };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @httpDelete("/:id")
 | 
			
		||||
    async delete(@requestParam('id') _id: string) {
 | 
			
		||||
        let result = this.client.deleteById(_id)
 | 
			
		||||
        return { status: result ? 0 : 1, msg: result ? '删除成功!' : '删除失败!' };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								packages/core/src/controller/page/service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								packages/core/src/controller/page/service.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
import { controller, get, post } from "@cc-server/binding";
 | 
			
		||||
 | 
			
		||||
@controller('/page/service')
 | 
			
		||||
class PageServiceController {
 | 
			
		||||
    @get('')
 | 
			
		||||
    index() {
 | 
			
		||||
        return {
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
import { controller, httpGet, requestParam } from 'inversify-express-utils';
 | 
			
		||||
import * as docker from '@dayu/docker-api'
 | 
			
		||||
 | 
			
		||||
@controller('/service')
 | 
			
		||||
class ServiceController {
 | 
			
		||||
    @httpGet('/list')
 | 
			
		||||
    public async list() {
 | 
			
		||||
        let services = await docker.service.list();
 | 
			
		||||
        return services.map(s => ({
 | 
			
		||||
            id: s.ID,
 | 
			
		||||
            name: s.Spec.Name
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @httpGet('/:id')
 | 
			
		||||
    public async details(@requestParam('id') id: string) {
 | 
			
		||||
        return await docker.service.inspect(id)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,22 +1,53 @@
 | 
			
		||||
import { CcServerBoot } from '@cc-server/core'
 | 
			
		||||
import { getContainer } from '@cc-server/ioc'
 | 
			
		||||
import { DBClient } from '@cc-server/db'
 | 
			
		||||
import { MongoCollection } from '@cc-server/db-mongo';
 | 
			
		||||
import { MongoClient, Db, Logger } from 'mongodb'
 | 
			
		||||
import * as fs from 'fs'
 | 
			
		||||
import * as path from 'path'
 | 
			
		||||
 | 
			
		||||
//process.env.DOCKER_HOST = 'https://ndcli.yumc.pw'
 | 
			
		||||
// process.env.DOCKER_HOST = '/var/run/docker.sock'
 | 
			
		||||
process.env.DOCKER_HOST = 'https://dscli.miaowoo.cc'
 | 
			
		||||
// process.env.DOCKER_HOST = 'https://dscli.miaowoo.cc'
 | 
			
		||||
// process.env.DOCKER_HOST = 'http://172.20.0.90:2378'
 | 
			
		||||
// process.env.DOCKER_HOST = 'https://dcli.yumc.pw'
 | 
			
		||||
process.env.DOCKER_HOST = 'http://172.16.200.12:8376'
 | 
			
		||||
let CC_MONGO_URL = process.env.CC_MONGO_URL
 | 
			
		||||
let CC_MONGO_DB = process.env.CC_MONGO_DB
 | 
			
		||||
// if (process.env.local) {
 | 
			
		||||
console.log("RUN AT LOCAL DOCKER!!!!!")
 | 
			
		||||
CC_MONGO_URL = "mongodb://192.168.2.5:27017"
 | 
			
		||||
CC_MONGO_DB = "dayu"
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
let server = new CcServerBoot();
 | 
			
		||||
const container = getContainer()
 | 
			
		||||
const server = new CcServerBoot(container);
 | 
			
		||||
 | 
			
		||||
let modulesDir = path.join(__dirname, 'controller')
 | 
			
		||||
let list = fs.readdirSync(modulesDir);
 | 
			
		||||
 | 
			
		||||
for (let file of list) {
 | 
			
		||||
function injectDBClient(db: Db, table: string) {
 | 
			
		||||
    server.container.bind(DBClient).toConstantValue(new MongoCollection(db.collection(table))).whenTargetNamed(table)
 | 
			
		||||
}
 | 
			
		||||
function requireDir(modulesDir: string) {
 | 
			
		||||
    let list = fs.readdirSync(modulesDir);
 | 
			
		||||
    for (let file of list) {
 | 
			
		||||
        let moduleDir = path.join(modulesDir, file)
 | 
			
		||||
        let stat = fs.statSync(moduleDir);
 | 
			
		||||
    if (stat.isFile() && file.endsWith('.js')) {
 | 
			
		||||
        if (stat.isDirectory()) {
 | 
			
		||||
            requireDir(moduleDir)
 | 
			
		||||
        } else if (stat.isFile() && file.endsWith('.js')) {
 | 
			
		||||
            require(moduleDir);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
server.static().build().start(81);
 | 
			
		||||
requireDir(path.join(__dirname, 'controller'))
 | 
			
		||||
 | 
			
		||||
MongoClient.connect(CC_MONGO_URL, { useNewUrlParser: true, connectTimeoutMS: 1000 }, (error, client) => {
 | 
			
		||||
    if (error) {
 | 
			
		||||
        console.log(error)
 | 
			
		||||
    } else {
 | 
			
		||||
        let db = client.db(CC_MONGO_DB);
 | 
			
		||||
        // Logger.setLevel('debug');
 | 
			
		||||
        injectDBClient(db, "page");
 | 
			
		||||
        server.start(81)
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
@@ -181,6 +181,13 @@ export declare namespace service {
 | 
			
		||||
        RollbackConfig: RollbackConfig;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export interface UpdateStatus {
 | 
			
		||||
        State: string;
 | 
			
		||||
        StartedAt: string;
 | 
			
		||||
        CompletedAt: string;
 | 
			
		||||
        Message: string;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export interface Service {
 | 
			
		||||
        ID: string;
 | 
			
		||||
        Version: Version;
 | 
			
		||||
@@ -189,7 +196,7 @@ export declare namespace service {
 | 
			
		||||
        Spec: Spec;
 | 
			
		||||
        Endpoint: Endpoint;
 | 
			
		||||
        PreviousSpec: PreviousSpec;
 | 
			
		||||
        UpdateStatus: UpdateStatus;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,9 @@ export namespace service {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    export async function inspect(id: string, query: { insertDefaults: boolean } = { insertDefaults: false }) {
 | 
			
		||||
        return await api.get<any>(`/services/${id}`, query);
 | 
			
		||||
        return await api.get<types.service.Service>(`/services/${id}`, query);
 | 
			
		||||
    }
 | 
			
		||||
    export async function update(id: string, query: { version: number, registryAuthFrom?: string, rollback?: string }, data: any) {
 | 
			
		||||
        return await api.post<any>(api.getUri(`/services/${id}/update`, query), data)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,13 @@ export async function stream<T = http.ServerResponse>(path: string, data?: objec
 | 
			
		||||
    return await handle<T>("GET", path, { params: data, responseType: "stream" });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getUri(path: string, data?: object) {
 | 
			
		||||
    return api.getUri({
 | 
			
		||||
        url: path,
 | 
			
		||||
        params: data
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function handle<T>(method: Method, path: string, reqConfig?: AxiosRequestConfig): Promise<T> {
 | 
			
		||||
    let config: AxiosRequestConfig = {
 | 
			
		||||
        method,
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,8 @@
 | 
			
		||||
        "Other"
 | 
			
		||||
    ],
 | 
			
		||||
    "activationEvents": [
 | 
			
		||||
        "*"
 | 
			
		||||
        "onView:docker-explorer",
 | 
			
		||||
        "onView:openfaas-explorer"
 | 
			
		||||
    ],
 | 
			
		||||
    "main": "./dist/extension.js",
 | 
			
		||||
    "contributes": {
 | 
			
		||||
@@ -60,8 +61,8 @@
 | 
			
		||||
        "vscode:prepublish": "yarn run compile",
 | 
			
		||||
        "compile": "tsc -p ./",
 | 
			
		||||
        "watch": "tsc -watch -p ./",
 | 
			
		||||
        "postinstall": "node ../../../node_modules/vscode/bin/install",
 | 
			
		||||
        "test": "yarn run compile && node ../../../node_modules/vscode/bin/test"
 | 
			
		||||
        "postinstall": "node ../../node_modules/vscode/bin/install",
 | 
			
		||||
        "test": "yarn run compile && node ../../node_modules/vscode/bin/test"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@dayu/docker-api": "^0.0.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
        "module": "commonjs",
 | 
			
		||||
        "sourceMap": true,
 | 
			
		||||
        "declaration": true,
 | 
			
		||||
        "declarationMap": true,
 | 
			
		||||
        "noImplicitAny": true,
 | 
			
		||||
        "allowUnreachableCode": true,
 | 
			
		||||
        "experimentalDecorators": true,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user