feat: add more docker api

master
MiaoWoo 2019-08-27 15:03:30 +08:00
parent f0810cc9d9
commit 3e480da539
20 changed files with 117 additions and 28 deletions

View File

@ -1,4 +1,4 @@
@url=https://dayu.n.yumc.pw @url=https://dayu-api.miaowoo.cc
### System ### System
##### Info ##### Info
@ -25,11 +25,22 @@ POST {{swarm}}/init
@stack={{url}}/stack @stack={{url}}/stack
##### Stack List ##### Stack List
GET {{stack}}/list GET {{stack}}/list
##### Stack Info
GET {{stack}}/faas
##### Stack Remove ##### Stack Remove
POST {{stack}}/develop/remove POST {{stack}}/develop/remove
### Service
@service={{url}}/service
##### Service List
GET {{service}}/list
##### Service Info
GET {{service}}/3gchxsmjld0fuex216w56jl5g
##### Service Remove
POST {{service}}/develop/remove
### Container ### Container
@container={{url}}/container @container={{url}}/container

View File

@ -7,7 +7,7 @@
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"clean": "npx lerna run clean", "clean": "npx lerna run clean",
"watch": "npx lerna run watch --concurrency 10", "watch": "npx lerna run watch --parallel",
"build": "npx lerna run build", "build": "npx lerna run build",
"lp": "npx lerna publish" "lp": "npx lerna publish"
}, },

View File

@ -26,6 +26,7 @@
"devDependencies": { "devDependencies": {
"@types/express": "^4.17.0", "@types/express": "^4.17.0",
"@types/socket.io": "^2.1.2", "@types/socket.io": "^2.1.2",
"nodemon": "^1.19.1",
"rimraf": "^2.6.3", "rimraf": "^2.6.3",
"ts-node-dev": "^1.0.0-pre.40", "ts-node-dev": "^1.0.0-pre.40",
"typescript": "^3.5.2" "typescript": "^3.5.2"
@ -43,4 +44,4 @@
"delay": "1500", "delay": "1500",
"ext": "js,json" "ext": "js,json"
} }
} }

View File

@ -0,0 +1,19 @@
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)
}
}

View File

@ -6,18 +6,25 @@ const STACK_LABEL = 'com.docker.stack.namespace';
@controller('/stack') @controller('/stack')
class StackController { class StackController {
@httpGet('/list') @httpGet('/list')
public async list() { public async list(): Promise<any> {
let stacks: { [key: string]: string[] } = {}; let stacks: { [key: string]: string[] } = {};
let result = [];
let services = await docker.service.list(); let services = await docker.service.list();
for (const service of services) { for (const service of services) {
let stackName = service.Spec.Labels[STACK_LABEL] let stackName = service.Spec.Labels[STACK_LABEL]
if (stackName) { if (stackName) {
let stack = stacks[stackName] || []; let stack = stacks[stackName];
if (!stack) {
result.push({
name: stackName,
services: stack = []
})
stacks[stackName] = stack;
}
stack.push(service.Spec.Name); stack.push(service.Spec.Name);
stacks[stackName] = stack;
} }
} }
return stacks; return result;
} }
@httpGet('/:stack') @httpGet('/:stack')
@ -31,11 +38,9 @@ class StackController {
} }
let services = await docker.service.list(filterOpt) let services = await docker.service.list(filterOpt)
let networks = await docker.network.list(filterOpt) let networks = await docker.network.list(filterOpt)
let containers = await docker.container.list(filterOpt);
return { return {
services: services.map(service => service.Spec.Name), services: services.map(service => service.Spec.Name),
networks: networks.map(network => network.Name), networks: networks.map(network => network.Name),
containers: containers.map(container => container.Names[0].substring(1))
} }
} }
} }

View File

@ -19,4 +19,4 @@ for (let file of list) {
} }
} }
server.static().build().start(); server.static().build().start(81);

View File

@ -1,7 +1,14 @@
{ {
"extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": "src", "baseUrl": "src",
"outDir": "dist" "outDir": "dist",
"target": "es6",
"module": "commonjs",
"sourceMap": true,
"declaration": true,
"noImplicitAny": true,
"allowUnreachableCode": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
} }
} }

View File

@ -17,7 +17,7 @@
"test": "echo \"Error: run tests from root\" && exit 1" "test": "echo \"Error: run tests from root\" && exit 1"
}, },
"dependencies": { "dependencies": {
"@cc-server/core": "^0.3.3", "@cc-server/core": "^0.6.1",
"axios": "^0.19.0" "axios": "^0.19.0"
}, },
"devDependencies": { "devDependencies": {

View File

@ -0,0 +1,6 @@
import * as common from './common'
export declare namespace node {
export interface ListOpts extends common.query.FilterOpt {
}
}

View File

@ -3,6 +3,18 @@ import { Labels } from '../common'
export declare namespace swarm { export declare namespace swarm {
type NodeAvailability = string; type NodeAvailability = string;
export interface UnlockOpts {
UnlockKey: string;
}
export interface JoinOpts {
ListenAddr?: string;
AdvertiseAddr?: string;
DataPathAddr?: string;
RemoteAddrs?: string[];
JoinToken?: string;
}
export interface InitOpts { export interface InitOpts {
ListenAddr?: string; ListenAddr?: string;
AdvertiseAddr?: string; AdvertiseAddr?: string;

View File

@ -297,4 +297,9 @@ export declare namespace container {
NetworkSettings: SummaryNetworkSettings; NetworkSettings: SummaryNetworkSettings;
Mounts: Mount[]; Mounts: Mount[];
} }
export interface ContainerPrune {
ContainersDeleted: string[];
SpaceReclaimed: number;
}
} }

View File

@ -8,16 +8,22 @@ export namespace container {
return await api.get<types.container.Container[]>('/containers/json', filters) return await api.get<types.container.Container[]>('/containers/json', filters)
} }
export async function info(id: string, query: { size: boolean } = { size: false }) { export async function inspect(id: string, query: { size: boolean } = { size: false }) {
return await api.get<types.container.ContainerJSON>(`/containers/${id}/json`, query); return await api.get<types.container.ContainerJSON>(`/containers/${id}/json`, query);
} }
export function prune() {
return api.post<types.container.ContainerPrune>('/containers/prune');
}
export async function logs(id: string, opts: opts.container.LogsOpts = {}): Promise<http.ServerResponse> { export async function logs(id: string, opts: opts.container.LogsOpts = {}): Promise<http.ServerResponse> {
return await api.stream(`/containers/${id}/logs`, Object.assign({ let data = {
follow: true, follow: true,
stdout: true, stdout: true,
stderr: true, stderr: true,
tail: 10 tail: 10,
}, opts)); ...opts
}
return await api.stream(`/containers/${id}/logs`, data);
} }
} }

View File

@ -7,6 +7,9 @@ export namespace service {
return await api.get<types.service.Service[]>('/services', filters); return await api.get<types.service.Service[]>('/services', filters);
} }
export async function create() { export async function create() {
} }
} export async function inspect(id: string, query: { insertDefaults: boolean } = { insertDefaults: false }) {
return await api.get<any>(`/services/${id}`, query);
}
}

View File

View File

@ -10,4 +10,20 @@ export namespace swarm {
export async function init(opts: opts.swarm.InitOpts) { export async function init(opts: opts.swarm.InitOpts) {
return await api.post<string>('/swarm/init', opts); return await api.post<string>('/swarm/init', opts);
} }
export async function join(opts: opts.swarm.JoinOpts) {
return await api.post<string>('/swarm/join', opts);
}
export async function leave(force: boolean = false) {
return await api.post<string>(`/swarm/leave?force=${force}`);
}
export async function unlockkey() {
return await api.get<string>(`/swarm/unlockkey`);
}
export async function unlock(opts: opts.swarm.UnlockOpts) {
return await api.post<string>(`/swarm/unlockkey`, opts);
}
} }

View File

@ -23,9 +23,9 @@ async function handle<T>(method: Method, path: string, reqConfig?: AxiosRequestC
let config: AxiosRequestConfig = { let config: AxiosRequestConfig = {
method, method,
url: path, url: path,
...reqConfig
}; };
let startTime = Date.now(); let startTime = Date.now();
Object.assign(config, reqConfig)
let response: AxiosResponse; let response: AxiosResponse;
try { try {
response = await api.request(config); response = await api.request(config);
@ -57,10 +57,6 @@ RESPONSE BODY : ${toString.call(response.data.pipe) === "[object Function]" ?
HANDLE TIME : ${Date.now() - startTime}ms HANDLE TIME : ${Date.now() - startTime}ms
=======================================`); =======================================`);
} }
// console.log(`${method} ${path} HTTP/1.1
// ${config.data ? JSON.stringify(config.data, null, 2) + '\n' : ''}
// HTTP/1.1 ${response.status} ${response.statusText}
// ${config.responseType != 'stream' ? JSON.stringify(response.data, null, 2) : config.responseType}`);
} }
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "@dayu/vscode", "name": "@dayu/vscode",
"displayName": "vscode", "displayName": "vscode",
"description": "", "description": "Dayu VsCode Plugin",
"publisher": "MiaoWoo", "publisher": "MiaoWoo",
"version": "0.0.1", "version": "0.0.1",
"engines": { "engines": {
@ -56,6 +56,7 @@
} }
}, },
"scripts": { "scripts": {
"package": "vsce package",
"vscode:prepublish": "yarn run compile", "vscode:prepublish": "yarn run compile",
"compile": "tsc -p ./", "compile": "tsc -p ./",
"watch": "tsc -watch -p ./", "watch": "tsc -watch -p ./",

View File

@ -7,6 +7,7 @@ import { OpenFaasProvider, DockerProvider } from './provider'
// this method is called when your extension is activated // this method is called when your extension is activated
// your extension is activated the very first time the command is executed // your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) { export function activate(context: vscode.ExtensionContext) {
console.log('init...')
new DockerProvider(context); new DockerProvider(context);
new OpenFaasProvider(context); new OpenFaasProvider(context);
} }

View File

@ -28,7 +28,7 @@ export class DockerProvider extends BaseProvider<vscode.TreeItem> {
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand('dayu.container.logs', (item: vscode.TreeItem) => { vscode.commands.registerCommand('dayu.container.logs', (item: vscode.TreeItem) => {
let value: ItemContextValue = JSON.parse(item.contextValue); let value: ItemContextValue = JSON.parse(item.contextValue);
let url = `https://faas.n.yumc.pw?action=container&data=${value.data.id}`; let url = `https://dayu-api.miaowoo.cc?action=container&data=${value.data.id}`;
return vscode.commands.executeCommand("mini-browser.openUrl", url); return vscode.commands.executeCommand("mini-browser.openUrl", url);
}), }),
vscode.window.registerTreeDataProvider('docker-explorer', this) vscode.window.registerTreeDataProvider('docker-explorer', this)

View File

@ -35,7 +35,7 @@ export class OpenFaasProvider extends BaseProvider<vscode.TreeItem> {
switch (value.type) { switch (value.type) {
case Type.ROOT: case Type.ROOT:
let funcs = await faas.getFunctions(); let funcs = await faas.getFunctions();
return funcs.map(f => { return funcs.map((f: any) => {
return this.createTreeItem({ return this.createTreeItem({
label: f.name, label: f.name,
tooltip: JSON.stringify(f, undefined, 2) tooltip: JSON.stringify(f, undefined, 2)