feat: add task and dashboard controller

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
MiaoWoo 2019-07-05 16:04:05 +08:00
parent c47137ec4a
commit 28d541b26f
9 changed files with 277 additions and 11 deletions

View File

@ -1,4 +1,4 @@
@url=https://faas.n.yumc.pw @url=https://dayu.n.yumc.pw
### System ### System
##### Info ##### Info
@ -36,3 +36,9 @@ POST {{stack}}/develop/remove
##### Container logs ##### Container logs
@id=6365041d2e52c5896dd14a5450920e482dddc33e6addaa07fab413bcda78d723 @id=6365041d2e52c5896dd14a5450920e482dddc33e6addaa07fab413bcda78d723
GET {{container}}/{{id}}/logs GET {{container}}/{{id}}/logs
### Dashboard
@dashboard={{url}}/dashboard
#####
GET {{dashboard}}

View File

@ -11,7 +11,7 @@
}, },
"scripts": { "scripts": {
"dev": "npx ts-node-dev --respawn --prefer-ts --debounce=1500 --ignore-watch=[] --project tsconfig.json", "dev": "npx ts-node-dev --respawn --prefer-ts --debounce=1500 --ignore-watch=[] --project tsconfig.json",
"debug": "npx nodemon -V --watch ../../node_modules --delay 1500ms dist/index.js", "debug": "npx nodemon dist/index.js",
"clean": "rimraf dist", "clean": "rimraf dist",
"watch": "npx tsc --watch", "watch": "npx tsc --watch",
"build": "yarn clean && npx tsc", "build": "yarn clean && npx tsc",
@ -29,5 +29,18 @@
"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"
},
"nodemonConfig": {
"verbose": true,
"ignore": [
".git",
"public"
],
"watch": [
"./",
"../../node_modules"
],
"delay": "1500",
"ext": "js,json"
} }
} }

View File

@ -34,10 +34,10 @@ socket.on('connect', () => {
case "container": case "container":
socket.emit('logs', { socket.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,
stderr: false, // stderr: false,
tail: "all" tail: "200"
}) })
break; break;
default: default:

View File

@ -0,0 +1,30 @@
import * as docker from '@dayu/docker-api'
import { controller, httpGet } from "@cc-server/binding";
const STACK_LABEL = 'com.docker.stack.namespace';
@controller('/dashboard')
class DashboardController {
@httpGet('')
async index() {
let stacks = [];
let services = [];
let svrs = await docker.service.list();
for (const service of svrs) {
if (service.Spec.Labels[STACK_LABEL]) {
stacks.push(service.Spec.Labels[STACK_LABEL]);
}
services.push(service.Spec.Name)
}
let networks = await docker.network.list();
let nodes = await docker.node.list();
let tasks = await docker.task.list();
return {
nodes: nodes.map(n => n.Description.Hostname),
tasks: tasks.map(t => t.ID),
stacks: Array.from(new Set(stacks)),
services,
networks: networks.map(n => n.Name)
}
}
}

View File

@ -1,4 +1,5 @@
export * from './node' export * from './node'
export * from './task'
export * from './swarm' export * from './swarm'
export * from './system' export * from './system'
export * from './network' export * from './network'

View File

@ -0,0 +1,178 @@
import { Options, Labels } from '../common'
export namespace task {
export interface Version {
Index: number;
}
export interface Privileges {
CredentialSpec?: any;
SELinuxContext?: any;
}
export interface DriverConfig {
Options: Options;
}
export interface VolumeOptions {
Labels: Labels;
DriverConfig: DriverConfig;
}
export interface Mount {
Type: string;
Source: string;
Target: string;
VolumeOptions: VolumeOptions;
ReadOnly?: boolean;
}
export interface File {
Name: string;
UID: string;
GID: string;
Mode: number;
}
export interface Secret {
File: File;
SecretID: string;
SecretName: string;
}
export interface ContainerSpec {
Image: string;
Labels: Labels;
Privileges: Privileges;
Mounts: Mount[];
Isolation: string;
Env: string[];
User: string;
Args: string[];
Secrets: Secret[];
}
export interface Limits {
MemoryBytes: any;
NanoCPUs?: number;
}
export interface Reservations {
MemoryBytes: any;
NanoCPUs?: number;
}
export interface Resources {
Limits: Limits;
Reservations: Reservations;
}
export interface Platform {
Architecture: string;
OS: string;
}
export interface Placement {
Constraints: string[];
Platforms: Platform[];
}
export interface Network {
Target: string;
Aliases: string[];
}
export interface RestartPolicy {
Condition: string;
MaxAttempts: number;
Delay?: number;
Window?: number;
}
export interface LogDriver {
Name: string;
Options: Options;
}
export interface Spec {
ContainerSpec: ContainerSpec;
Resources: Resources;
Placement: Placement;
Networks: Network[];
ForceUpdate: number;
RestartPolicy: RestartPolicy;
LogDriver: LogDriver;
}
export interface ContainerStatus {
ContainerID: string;
PID: number;
ExitCode: number;
}
export interface Port {
Protocol: string;
TargetPort: number;
PublishedPort: number;
PublishMode: string;
}
export interface PortStatus {
Ports: Port[];
}
export interface Status {
Timestamp: string;
State: string;
Message: string;
Err: string;
ContainerStatus: ContainerStatus;
PortStatus: PortStatus;
}
export interface DriverConfiguration {
Name: string;
}
export interface Driver {
Name: string;
}
export interface Config {
Subnet: string;
Gateway: string;
}
export interface IPAMOptions {
Driver: Driver;
Configs: Config[];
}
export interface DriverState {
Name: string;
Options: Options;
}
export interface NetworksAttachment {
Network: Network;
Addresses: string[];
}
export interface Task {
ID: string;
Version: Version;
CreatedAt: string;
UpdatedAt: any;
Labels: Labels;
Spec: Spec;
ServiceID: string;
Slot: number;
NodeID: string;
Status: Status;
DesiredState: string;
NetworksAttachments: NetworksAttachment[];
}
}

View File

@ -1,4 +1,5 @@
export * from './node' export * from './node'
export * from './task'
export * from './swarm' export * from './swarm'
export * from './system' export * from './system'
export * from './network' export * from './network'

View File

@ -0,0 +1,8 @@
import * as api from '../utils/api'
import * as types from '../api/types'
export namespace task {
export async function list() {
return await api.get<types.task.Task[]>('/tasks');
}
}

View File

@ -17,7 +17,8 @@ enum Type {
NODE = "NODE" NODE = "NODE"
} }
let TREE_LIST = [Type.NODES, Type.CONTAINERS, Type.SERVICES, Type.NETWORKS] let TREE_LIST = [Type.NODES, Type.CONTAINERS, Type.SERVICES, Type.STACKS, Type.NETWORKS]
const STACK_LABEL = 'com.docker.stack.namespace';
export class DockerProvider extends BaseProvider<vscode.TreeItem> { export class DockerProvider extends BaseProvider<vscode.TreeItem> {
onDidChangeTreeData?: vscode.Event<vscode.TreeItem | null | undefined> | undefined; onDidChangeTreeData?: vscode.Event<vscode.TreeItem | null | undefined> | undefined;
@ -117,9 +118,37 @@ export class DockerProvider extends BaseProvider<vscode.TreeItem> {
tooltip: JSON.stringify(n, undefined, 2) tooltip: JSON.stringify(n, undefined, 2)
}) })
}) })
case Type.CONTAINER: case Type.STACKS:
let stacks: { [key: string]: string[] } = {};
break; let svrs = await docker.service.list();
for (const service of svrs) {
let stackName = service.Spec.Labels[STACK_LABEL]
if (stackName) {
let stack = stacks[stackName] || [];
stack.push(service.Spec.Name);
stacks[stackName] = stack;
}
}
return Object.keys(stacks).map(stack => {
return this.createTreeItem({
label: stack,
context: {
type: Type.STACK,
data: {
name: stack,
list: stacks[stack]
}
},
state: vscode.TreeItemCollapsibleState.Collapsed
})
})
case Type.STACK:
let list: string[] = value.data.list;
return list.map(s => {
return this.createTreeItem({
label: s
})
})
default: default:
} }
return []; return [];