feat: add image volume controller
Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
@url=https://dcli.yumc.pw/v1.39
|
@url=https://dscli.miaowoo.cc/v1.39
|
||||||
|
|
||||||
### Info
|
### Info
|
||||||
GET {{url}}/info
|
GET {{url}}/info
|
||||||
@@ -25,12 +25,79 @@ GET {{container}}/json?filters={"label":{"com.docker.stack.namespace%3Dmonitor":
|
|||||||
##### In
|
##### In
|
||||||
GET {{container}}/{{cid}}/json
|
GET {{container}}/{{cid}}/json
|
||||||
|
|
||||||
### Services
|
### Services ?filters={"mode":["global"]}
|
||||||
GET {{url}}/services?filters={"mode":["global"]}
|
GET {{url}}/services
|
||||||
|
|
||||||
### Create Services
|
##### Create Services
|
||||||
POST {{url}}/services/create
|
POST {{url}}/services/create
|
||||||
|
|
||||||
{
|
{
|
||||||
|
"Name": "analysis_tera-200706",
|
||||||
}
|
"Labels": {
|
||||||
|
"com.docker.stack.image": "miaowoo/tera:frp",
|
||||||
|
"com.docker.stack.namespace": "analysis"
|
||||||
|
},
|
||||||
|
"TaskTemplate": {
|
||||||
|
"ContainerSpec": {
|
||||||
|
"Image": "miaowoo/tera:frp",
|
||||||
|
"Labels": {
|
||||||
|
"com.docker.stack.namespace": "analysis"
|
||||||
|
},
|
||||||
|
"Env": [
|
||||||
|
"FRP_NAME=tera-200706",
|
||||||
|
"FRP_TOKEN=Jtb2hwwfor",
|
||||||
|
"FRP_USER=MiaoWoo",
|
||||||
|
"PASSWD=Jtb2hwwfor",
|
||||||
|
"TERA_COUNT_MINING_CPU=8",
|
||||||
|
"TERA_NET_WORK_MODE_IP=60.12.241.181",
|
||||||
|
"TERA_NET_WORK_MODE_PORT=30019",
|
||||||
|
"TERA_REST_START_COUNT=100000",
|
||||||
|
"TERA_WALLET_MINING_ACCOUNT=200706",
|
||||||
|
"TERA_WATCHDOG_BADACCOUNT=2"
|
||||||
|
],
|
||||||
|
"Privileges": {
|
||||||
|
"CredentialSpec": null,
|
||||||
|
"SELinuxContext": null
|
||||||
|
},
|
||||||
|
"Init": true,
|
||||||
|
"Mounts": [
|
||||||
|
{
|
||||||
|
"Type": "bind",
|
||||||
|
"Source": "/home/app/tera/DATA",
|
||||||
|
"Target": "/app/DATA"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Isolation": "default"
|
||||||
|
},
|
||||||
|
"Resources": {
|
||||||
|
"Limits": {
|
||||||
|
"NanoCPUs": 9000000000,
|
||||||
|
"MemoryBytes": 38654705664
|
||||||
|
},
|
||||||
|
"Reservations": {
|
||||||
|
"NanoCPUs": 8000000000,
|
||||||
|
"MemoryBytes": 34359738368
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Placement": {
|
||||||
|
"Constraints": [
|
||||||
|
"node.hostname == manager1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ForceUpdate": 0,
|
||||||
|
"Runtime": "container"
|
||||||
|
},
|
||||||
|
"Mode": {
|
||||||
|
"Replicated": {
|
||||||
|
"Replicas": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"EndpointSpec": {
|
||||||
|
"Mode": "vip"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
### Delete Services
|
||||||
|
@id=t6yn64q53q1dmgzdr8td8crbl
|
||||||
|
DELETE {{url}}/services/{{id}}
|
||||||
|
|
||||||
|
|||||||
@@ -22,17 +22,30 @@ location.search.substring(1).split("&").forEach(q => {
|
|||||||
|
|
||||||
console.log(query);
|
console.log(query);
|
||||||
|
|
||||||
var socket = io('/container', {
|
var system = io('/', {
|
||||||
path: '/ws',
|
path: '/ws',
|
||||||
transports: ['websocket']
|
transports: ['websocket']
|
||||||
});
|
});
|
||||||
socket.on('connect', () => {
|
|
||||||
|
system.on('connect', () => {
|
||||||
|
system.emit('events', {})
|
||||||
|
})
|
||||||
|
|
||||||
|
system.on('message', data => {
|
||||||
|
term.write(data.toString() + '\r\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
var container = io('/container', {
|
||||||
|
path: '/ws',
|
||||||
|
transports: ['websocket']
|
||||||
|
});
|
||||||
|
container.on('connect', () => {
|
||||||
term.writeln('connect')
|
term.writeln('connect')
|
||||||
if (query.action) {
|
if (query.action) {
|
||||||
term.writeln(`Recover Action: ${query.action} Data: ${query.data}`)
|
term.writeln(`Recover Action: ${query.action} Data: ${query.data}`)
|
||||||
switch (query.action) {
|
switch (query.action) {
|
||||||
case "container":
|
case "container":
|
||||||
socket.emit('logs', {
|
container.emit('logs', {
|
||||||
id: query.data,
|
id: query.data,
|
||||||
// since: Date.now() / 1000 - 60 * 15,
|
// since: Date.now() / 1000 - 60 * 15,
|
||||||
// until: Date.now() / 1000,
|
// until: Date.now() / 1000,
|
||||||
@@ -51,7 +64,7 @@ term.on('data', async data => {
|
|||||||
term.write(data);
|
term.write(data);
|
||||||
if (data == '\r') {
|
if (data == '\r') {
|
||||||
term.write('\n');
|
term.write('\n');
|
||||||
socket.emit('logs', {
|
container.emit('logs', {
|
||||||
id: command
|
id: command
|
||||||
})
|
})
|
||||||
command = '';
|
command = '';
|
||||||
@@ -59,10 +72,10 @@ term.on('data', async data => {
|
|||||||
command += data;
|
command += data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
socket.on('message', data => {
|
container.on('message', data => {
|
||||||
term.write(data.toString() + '\r\n');
|
term.write(data.toString() + '\r\n');
|
||||||
});
|
});
|
||||||
socket.on('disconnect', () => {
|
container.on('disconnect', () => {
|
||||||
term.reset();
|
term.reset();
|
||||||
term.writeln('disconnect');
|
term.writeln('disconnect');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,12 +19,18 @@ class DashboardController {
|
|||||||
let networks = await docker.network.list();
|
let networks = await docker.network.list();
|
||||||
let nodes = await docker.node.list();
|
let nodes = await docker.node.list();
|
||||||
let tasks = await docker.task.list();
|
let tasks = await docker.task.list();
|
||||||
|
let containers = await docker.container.list();
|
||||||
|
let images = await docker.image.list();
|
||||||
|
let volumes = await docker.volume.list();
|
||||||
return {
|
return {
|
||||||
nodes: nodes.map(n => n.Description.Hostname),
|
nodes: nodes.map(n => n.Description.Hostname),
|
||||||
tasks: tasks.map(t => t.ID),
|
tasks: tasks.map(t => t.ID),
|
||||||
stacks: Array.from(new Set(stacks)),
|
stacks: Array.from(new Set(stacks)),
|
||||||
services,
|
services,
|
||||||
networks: networks.map(n => n.Name)
|
networks: networks.map(n => n.Name),
|
||||||
|
containers: containers.map(c => c.Names),
|
||||||
|
images: images.map(i => i.Id),
|
||||||
|
volumes: volumes.Volumes.map(v => v.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { controller, httpGet, httpPost } from 'inversify-express-utils';
|
import { controller, httpGet, httpPost } from 'inversify-express-utils';
|
||||||
import * as docker from '@dayu/docker-api'
|
import * as docker from '@dayu/docker-api'
|
||||||
|
import { io, namespace, listener, interfaces, Message } from '@cc-server/ws';
|
||||||
|
|
||||||
@controller('')
|
@controller('')
|
||||||
class SystemController {
|
class SystemController {
|
||||||
@@ -14,9 +15,32 @@ class SystemController {
|
|||||||
}
|
}
|
||||||
@httpGet('/events')
|
@httpGet('/events')
|
||||||
public async event() {
|
public async event() {
|
||||||
await docker.system.events((event) => {
|
let stream = await docker.system.events();
|
||||||
if (!event) { return }
|
stream.on('data', (chunk: ArrayBuffer) => {
|
||||||
console.log(event)
|
let log = Buffer.from(chunk).toString();
|
||||||
|
console.log(log);
|
||||||
})
|
})
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@namespace()
|
||||||
|
class SystemNamespace extends interfaces.Namespace {
|
||||||
|
@listener()
|
||||||
|
async events(socket: io.Socket) {
|
||||||
|
try {
|
||||||
|
socket.send('Starting listening docker event...');
|
||||||
|
let stream = await docker.system.events();
|
||||||
|
socket.send('Connect to docker deamon...');
|
||||||
|
this.defer(socket, () => stream.connection.destroy());
|
||||||
|
stream.on('data', (chunk: ArrayBuffer) => {
|
||||||
|
let log = Buffer.from(chunk).toString();
|
||||||
|
console.log(log);
|
||||||
|
socket.send(log);
|
||||||
|
})
|
||||||
|
} catch (ex) {
|
||||||
|
//console.error(ex);
|
||||||
|
return new Message(ex.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,8 @@ import * as fs from 'fs'
|
|||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
|
||||||
//process.env.DOCKER_HOST = 'https://ndcli.yumc.pw'
|
//process.env.DOCKER_HOST = 'https://ndcli.yumc.pw'
|
||||||
process.env.DOCKER_HOST = '/var/run/docker.sock'
|
// process.env.DOCKER_HOST = '/var/run/docker.sock'
|
||||||
|
process.env.DOCKER_HOST = 'https://dscli.miaowoo.cc'
|
||||||
|
|
||||||
let server = new CcServerBoot();
|
let server = new CcServerBoot();
|
||||||
|
|
||||||
|
|||||||
17
packages/docker-api/src/api/types/image.ts
Normal file
17
packages/docker-api/src/api/types/image.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Labels } from '../common'
|
||||||
|
|
||||||
|
export declare namespace image {
|
||||||
|
export interface Image {
|
||||||
|
Containers: number;
|
||||||
|
Created: number;
|
||||||
|
Id: string;
|
||||||
|
Labels: Labels;
|
||||||
|
ParentId: string;
|
||||||
|
RepoDigests: string[];
|
||||||
|
RepoTags: string[];
|
||||||
|
SharedSize: number;
|
||||||
|
Size: number;
|
||||||
|
VirtualSize: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
export * from './node'
|
export * from './node'
|
||||||
export * from './task'
|
export * from './task'
|
||||||
|
export * from './image'
|
||||||
export * from './swarm'
|
export * from './swarm'
|
||||||
|
export * from './volume'
|
||||||
export * from './system'
|
export * from './system'
|
||||||
export * from './network'
|
export * from './network'
|
||||||
export * from './service'
|
export * from './service'
|
||||||
|
|||||||
19
packages/docker-api/src/api/types/volume.ts
Normal file
19
packages/docker-api/src/api/types/volume.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { Labels, Options } from '../common'
|
||||||
|
|
||||||
|
export declare namespace volume {
|
||||||
|
export interface Volume {
|
||||||
|
CreatedAt: Date;
|
||||||
|
Driver: string;
|
||||||
|
Labels: Labels;
|
||||||
|
Mountpoint: string;
|
||||||
|
Name: string;
|
||||||
|
Options: Options;
|
||||||
|
Scope: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VolumeJSON {
|
||||||
|
Volumes: Volume[];
|
||||||
|
Warnings?: any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
8
packages/docker-api/src/client/image.ts
Normal file
8
packages/docker-api/src/client/image.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import * as api from '../utils/api'
|
||||||
|
import * as types from '../api/types'
|
||||||
|
|
||||||
|
export namespace image {
|
||||||
|
export async function list() {
|
||||||
|
return await api.get<types.image.Image[]>('/images/json');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
export * from './node'
|
export * from './node'
|
||||||
export * from './task'
|
export * from './task'
|
||||||
|
export * from './image'
|
||||||
export * from './swarm'
|
export * from './swarm'
|
||||||
|
export * from './volume'
|
||||||
export * from './system'
|
export * from './system'
|
||||||
export * from './network'
|
export * from './network'
|
||||||
export * from './service'
|
export * from './service'
|
||||||
|
|||||||
@@ -6,4 +6,7 @@ export namespace service {
|
|||||||
export async function list(filters?: opts.service.ListOpts) {
|
export async function list(filters?: opts.service.ListOpts) {
|
||||||
return await api.get<types.service.Service[]>('/services', filters);
|
return await api.get<types.service.Service[]>('/services', filters);
|
||||||
}
|
}
|
||||||
|
export async function create() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,13 +10,7 @@ export namespace system {
|
|||||||
return await api.get<types.system.Version>('/version');
|
return await api.get<types.system.Version>('/version');
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function events(cb: (events: object) => void) {
|
export async function events() {
|
||||||
let stream = await api.stream<any>('/events');
|
return await api.stream('/events');
|
||||||
stream.on('data', (chunk: ArrayBuffer) => {
|
|
||||||
cb(JSON.parse(Buffer.from(chunk).toString()))
|
|
||||||
})
|
|
||||||
stream.on('end', () => {
|
|
||||||
cb(undefined);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
packages/docker-api/src/client/volume.ts
Normal file
8
packages/docker-api/src/client/volume.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import * as api from '../utils/api'
|
||||||
|
import * as types from '../api/types'
|
||||||
|
|
||||||
|
export namespace volume {
|
||||||
|
export async function list() {
|
||||||
|
return await api.get<types.volume.VolumeJSON>('/volumes');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,10 @@ export async function post<T>(path: string, data?: object): Promise<T> {
|
|||||||
return await handle<T>("POST", path, { data });
|
return await handle<T>("POST", path, { data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function del<T>(path: string, data?: object): Promise<T> {
|
||||||
|
return await handle<T>("DELETE", path, { params: data });
|
||||||
|
}
|
||||||
|
|
||||||
export async function stream<T = http.ServerResponse>(path: string, data?: object): Promise<T> {
|
export async function stream<T = http.ServerResponse>(path: string, data?: object): Promise<T> {
|
||||||
return await handle<T>("GET", path, { params: data, responseType: "stream" });
|
return await handle<T>("GET", path, { params: data, responseType: "stream" });
|
||||||
}
|
}
|
||||||
@@ -64,8 +68,7 @@ function init() {
|
|||||||
const instanceConfig: AxiosRequestConfig = {
|
const instanceConfig: AxiosRequestConfig = {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
}
|
||||||
timeout: 5000
|
|
||||||
}
|
}
|
||||||
if (process.env.DOCKER_HOST.startsWith("/")) {
|
if (process.env.DOCKER_HOST.startsWith("/")) {
|
||||||
instanceConfig.socketPath = process.env.DOCKER_HOST
|
instanceConfig.socketPath = process.env.DOCKER_HOST
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"name": "@dayu/vscode",
|
"name": "@dayu/vscode",
|
||||||
"displayName": "vscode",
|
"displayName": "vscode",
|
||||||
"description": "",
|
"description": "",
|
||||||
|
"publisher": "MiaoWoo",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"vscode": "^1.35.0"
|
"vscode": "^1.35.0"
|
||||||
@@ -73,4 +74,4 @@
|
|||||||
"typescript": "^3.3.1",
|
"typescript": "^3.3.1",
|
||||||
"vscode": "^1.1.28"
|
"vscode": "^1.1.28"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user