feat: class ful docker api client
This commit is contained in:
parent
84c304a26a
commit
e53f633498
@ -7,4 +7,13 @@ export declare namespace query {
|
||||
[key: string]: boolean
|
||||
}
|
||||
}
|
||||
}
|
||||
export interface LogsOpts {
|
||||
follow?: boolean;
|
||||
stdout?: boolean;
|
||||
stderr?: boolean;
|
||||
since?: number;
|
||||
until?: number;
|
||||
timestamps?: boolean;
|
||||
tail?: number | "all";
|
||||
}
|
@ -6,14 +6,7 @@ export declare namespace container {
|
||||
limit?: number;
|
||||
size?: boolean;
|
||||
}
|
||||
export interface LogsOpts {
|
||||
follow?: boolean;
|
||||
stdout?: boolean;
|
||||
stderr?: boolean;
|
||||
since?: number;
|
||||
until?: number;
|
||||
timestamps?: boolean;
|
||||
tail?: number | "all";
|
||||
export interface LogsOpts extends common.LogsOpts {
|
||||
}
|
||||
export namespace exec {
|
||||
export interface Create {
|
||||
|
@ -1,3 +1,4 @@
|
||||
export * from './task'
|
||||
export * from './swarm'
|
||||
export * from './common'
|
||||
export * from './config'
|
||||
|
@ -2,16 +2,8 @@ import * as common from './common'
|
||||
|
||||
export declare namespace service {
|
||||
export interface FilterOpt {
|
||||
|
||||
|
||||
}
|
||||
export interface LogsOpts {
|
||||
details?: boolean;
|
||||
follow?: boolean;
|
||||
stdout?: boolean;
|
||||
stderr?: boolean;
|
||||
since?: number;
|
||||
until?: number;
|
||||
timestamps?: boolean;
|
||||
tail?: number | "all";
|
||||
export interface LogsOpts extends common.LogsOpts {
|
||||
}
|
||||
}
|
9
packages/docker-api/src/api/opts/task.ts
Normal file
9
packages/docker-api/src/api/opts/task.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import * as common from './common'
|
||||
|
||||
export declare namespace task {
|
||||
export interface FilterOpt {
|
||||
|
||||
}
|
||||
export interface LogsOpts extends common.LogsOpts {
|
||||
}
|
||||
}
|
92
packages/docker-api/src/client/api.ts
Normal file
92
packages/docker-api/src/client/api.ts
Normal file
@ -0,0 +1,92 @@
|
||||
import { ServerResponse } from 'http'
|
||||
import axios, { AxiosInstance, AxiosRequestConfig, Method, AxiosResponse } from 'axios';
|
||||
export interface DockerApiClient {
|
||||
get<T>(path: string, data?: object): Promise<T>;
|
||||
post<T>(path: string, data?: object): Promise<T>;
|
||||
del<T>(path: string, data?: object): Promise<T>;
|
||||
stream<T = ServerResponse>(path: string, data?: object): Promise<T>;
|
||||
getUri(path: string, data?: object): string;
|
||||
}
|
||||
|
||||
class DefaultDockerApiClient implements DockerApiClient {
|
||||
private api: AxiosInstance;
|
||||
constructor(host: string = process.env.DOCKER_HOST) {
|
||||
const instanceConfig: AxiosRequestConfig = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
if (host.startsWith("/")) {
|
||||
instanceConfig.socketPath = host
|
||||
} else {
|
||||
instanceConfig.baseURL = host
|
||||
}
|
||||
this.api = axios.create(instanceConfig)
|
||||
}
|
||||
async get<T>(path: string, data?: object): Promise<T> {
|
||||
return await this.handle<T>("GET", path, { params: data });
|
||||
}
|
||||
|
||||
async post<T>(path: string, data?: object): Promise<T> {
|
||||
return await this.handle<T>("POST", path, { data });
|
||||
}
|
||||
|
||||
async del<T>(path: string, data?: object): Promise<T> {
|
||||
return await this.handle<T>("DELETE", path, { params: data });
|
||||
}
|
||||
|
||||
async stream<T = ServerResponse>(path: string, data?: object): Promise<T> {
|
||||
return await this.handle<T>("GET", path, { params: data, responseType: "stream" });
|
||||
}
|
||||
|
||||
getUri(path: string, data?: object): string {
|
||||
return this.api.getUri({
|
||||
url: path,
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
async handle<T>(method: Method, path: string, reqConfig?: AxiosRequestConfig): Promise<T> {
|
||||
let config: AxiosRequestConfig = {
|
||||
method,
|
||||
url: path,
|
||||
...reqConfig
|
||||
};
|
||||
let startTime = Date.now();
|
||||
let response: AxiosResponse;
|
||||
try {
|
||||
response = await this.api.request(config);
|
||||
return response.data as T
|
||||
} catch (ex) {
|
||||
if (!ex.response) { throw ex; }
|
||||
response = ex.response;
|
||||
if (response.status > 299 && config.responseType == "stream") {
|
||||
let stream = response.data;
|
||||
response.data = await new Promise<T>((resolve, reject) => {
|
||||
let cache = '';
|
||||
stream.on('data', (chunk: ArrayBuffer) => {
|
||||
cache += chunk.toString()
|
||||
})
|
||||
stream.on('end', () => {
|
||||
resolve(JSON.parse(cache) as T);
|
||||
})
|
||||
})
|
||||
}
|
||||
throw new Error(JSON.stringify(response.data));
|
||||
} finally {
|
||||
if (response) {
|
||||
console.log(`========== Docker API Invoke ==========
|
||||
REQUEST METHOD : ${method}
|
||||
REQUEST PATH : ${response.request.path}
|
||||
REQUEST PARAMS : ${config.params ? JSON.stringify(config.params) : ''}
|
||||
REQUEST BODY : ${config.data ? JSON.stringify(config.data) : ''}
|
||||
RESPONSE BODY : ${toString.call(response.data.pipe) === "[object Function]" ? '<Stream>' : JSON.stringify(response.data)}
|
||||
HANDLE TIME : ${Date.now() - startTime}ms
|
||||
=======================================`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default new DefaultDockerApiClient();
|
@ -1,18 +1,20 @@
|
||||
import * as api from '../utils/api'
|
||||
import * as opts from '../api/opts'
|
||||
import * as types from '../api/types'
|
||||
import * as filterUtil from '../api/opts/filter'
|
||||
import { DockerApiClient } from './api';
|
||||
|
||||
export namespace config {
|
||||
export async function list(filter?: opts.config.FilterOpt) {
|
||||
return await api.get<types.config.Config[]>('/configs', {
|
||||
export class Config {
|
||||
constructor(public api: DockerApiClient) {
|
||||
}
|
||||
list(filter?: opts.config.FilterOpt) {
|
||||
return this.api.get<types.config.Config[]>('/configs', {
|
||||
filters: filterUtil.toJSON(filter)
|
||||
});
|
||||
}
|
||||
export async function inspect(id: string) {
|
||||
return await api.get(`/configs/${id}`)
|
||||
inspect(id: string) {
|
||||
return this.api.get(`/configs/${id}`)
|
||||
}
|
||||
export async function create() {
|
||||
return await api.post<{}>('/configs/create')
|
||||
create() {
|
||||
return this.api.post<{}>('/configs/create')
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,31 @@
|
||||
import * as api from '../utils/api';
|
||||
import * as opts from '../api/opts'
|
||||
import * as types from '../api/types'
|
||||
import * as http from 'http'
|
||||
import { DockerApiClient } from './api';
|
||||
|
||||
export namespace container {
|
||||
export async function list(filters?: opts.container.ListOpts) {
|
||||
return await api.get<types.container.Container[]>('/containers/json', filters)
|
||||
export class Container {
|
||||
private execClient: Exec;
|
||||
constructor(public api: DockerApiClient) {
|
||||
this.execClient = new Exec(api);
|
||||
}
|
||||
|
||||
export async function inspect(id: string, query: { size: boolean } = { size: false }) {
|
||||
return await api.get<types.container.ContainerJSON>(`/containers/${id}/json`, query);
|
||||
get exec() {
|
||||
return this.execClient;
|
||||
}
|
||||
|
||||
export function prune() {
|
||||
return api.post<types.container.ContainerPrune>('/containers/prune');
|
||||
async list(filters?: opts.container.ListOpts) {
|
||||
return await this.api.get<types.container.Container[]>('/containers/json', filters)
|
||||
}
|
||||
|
||||
export async function logs(id: string, opts: opts.container.LogsOpts = {}): Promise<http.ServerResponse> {
|
||||
async inspect(id: string, query: { size: boolean } = { size: false }) {
|
||||
return await this.api.get<types.container.ContainerJSON>(`/containers/${id}/json`, query);
|
||||
}
|
||||
|
||||
prune() {
|
||||
return this.api.post<types.container.ContainerPrune>('/containers/prune');
|
||||
}
|
||||
|
||||
async logs(id: string, opts: opts.container.LogsOpts = {}): Promise<http.ServerResponse> {
|
||||
let data = {
|
||||
follow: true,
|
||||
stdout: true,
|
||||
@ -24,31 +33,32 @@ export namespace container {
|
||||
tail: 10,
|
||||
...opts
|
||||
}
|
||||
return await api.stream(`/containers/${id}/logs`, data);
|
||||
}
|
||||
|
||||
export namespace exec {
|
||||
export function create(id: string, opts: opts.container.exec.Create = {}): Promise<types.container.exec.CreateResult> {
|
||||
let request = {
|
||||
AttachStdin: true,
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
DetachKeys: 'ctrl-d',
|
||||
Tty: true,
|
||||
Cmd: '/bin/sh',
|
||||
...opts
|
||||
}
|
||||
request.AttachStderr = true
|
||||
return api.post<types.container.exec.CreateResult>(`/containers/${id}/exec`, request)
|
||||
}
|
||||
export function start(id: string, opts: opts.container.exec.Start = {}) {
|
||||
return api.post<types.container.exec.StartResult>(`/exec/${id}/start`, opts)
|
||||
}
|
||||
export function resize(id: string, opts: opts.container.exec.Resize = {}) {
|
||||
return api.post<types.container.exec.ResizeResult>(`/exec/${id}/resize`, opts)
|
||||
}
|
||||
export function inspect(id: string) {
|
||||
return api.get<types.container.exec.ExecJson>(`/exec/${id}/json`)
|
||||
}
|
||||
return await this.api.stream(`/containers/${id}/logs`, data);
|
||||
}
|
||||
}
|
||||
|
||||
class Exec {
|
||||
constructor(public api: DockerApiClient) { }
|
||||
create(id: string, opts: opts.container.exec.Create = {}): Promise<types.container.exec.CreateResult> {
|
||||
let request = {
|
||||
AttachStdin: true,
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
DetachKeys: 'ctrl-d',
|
||||
Tty: true,
|
||||
Cmd: '/bin/sh',
|
||||
...opts
|
||||
}
|
||||
request.AttachStderr = true
|
||||
return this.api.post<types.container.exec.CreateResult>(`/containers/${id}/exec`, request)
|
||||
}
|
||||
start(id: string, opts: opts.container.exec.Start = {}) {
|
||||
return this.api.post<types.container.exec.StartResult>(`/exec/${id}/start`, opts)
|
||||
}
|
||||
resize(id: string, opts: opts.container.exec.Resize = {}) {
|
||||
return this.api.post<types.container.exec.ResizeResult>(`/exec/${id}/resize`, opts)
|
||||
}
|
||||
inspect(id: string) {
|
||||
return this.api.get<types.container.exec.ExecJson>(`/exec/${id}/json`)
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
import * as api from '../utils/api'
|
||||
import * as types from '../api/types'
|
||||
import { DockerApiClient } from './api';
|
||||
|
||||
export namespace image {
|
||||
export async function list() {
|
||||
return await api.get<types.image.Image[]>('/images/json');
|
||||
export class Image {
|
||||
constructor(public api: DockerApiClient) {
|
||||
}
|
||||
list() {
|
||||
return this.api.get<types.image.Image[]>('/images/json');
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,67 @@
|
||||
export * from './node'
|
||||
export * from './task'
|
||||
export * from './image'
|
||||
export * from './swarm'
|
||||
export * from './config'
|
||||
export * from './volume'
|
||||
export * from './system'
|
||||
export * from './network'
|
||||
export * from './service'
|
||||
export * from './container'
|
||||
import api, { DockerApiClient } from './api'
|
||||
import { Container } from './container'
|
||||
import { Service } from './service'
|
||||
import { Node } from './node'
|
||||
import { Task } from './task'
|
||||
import { Image } from './image'
|
||||
import { Swarm } from './swarm'
|
||||
import { Config } from './config'
|
||||
import { Volume } from './volume'
|
||||
import { System } from './system'
|
||||
import { Network } from './network'
|
||||
export class DockerClient {
|
||||
private containerInstance: Container;
|
||||
private serviceInstance: Service;
|
||||
private nodeInstance: Node;
|
||||
private taskInstance: Task;
|
||||
private imageInstance: Image;
|
||||
private swarmInstance: Swarm;
|
||||
private configInstance: Config;
|
||||
private volumeInstance: Volume;
|
||||
private systemInstance: System;
|
||||
private networkInstance: Network;
|
||||
constructor(apiClient: DockerApiClient = api) {
|
||||
this.containerInstance = new Container(apiClient)
|
||||
this.serviceInstance = new Service(apiClient)
|
||||
this.nodeInstance = new Node(apiClient)
|
||||
this.taskInstance = new Task(apiClient)
|
||||
this.imageInstance = new Image(apiClient)
|
||||
this.swarmInstance = new Swarm(apiClient)
|
||||
this.configInstance = new Config(apiClient)
|
||||
this.volumeInstance = new Volume(apiClient)
|
||||
this.systemInstance = new System(apiClient)
|
||||
this.networkInstance = new Network(apiClient)
|
||||
}
|
||||
get container() {
|
||||
return this.containerInstance;
|
||||
}
|
||||
get service() {
|
||||
return this.serviceInstance;
|
||||
}
|
||||
get node() {
|
||||
return this.nodeInstance;
|
||||
}
|
||||
get task() {
|
||||
return this.taskInstance;
|
||||
}
|
||||
get image() {
|
||||
return this.imageInstance;
|
||||
}
|
||||
get swarm() {
|
||||
return this.swarmInstance;
|
||||
}
|
||||
get config() {
|
||||
return this.configInstance;
|
||||
}
|
||||
get volume() {
|
||||
return this.volumeInstance;
|
||||
}
|
||||
get system() {
|
||||
return this.systemInstance;
|
||||
}
|
||||
get network() {
|
||||
return this.networkInstance;
|
||||
}
|
||||
}
|
||||
|
||||
export default new DockerClient();
|
@ -1,9 +1,11 @@
|
||||
import * as api from '../utils/api'
|
||||
import * as opts from '../api/opts'
|
||||
import * as types from '../api/types'
|
||||
import { DockerApiClient } from './api'
|
||||
|
||||
export namespace network {
|
||||
export async function list(opts?: opts.network.ListOpts) {
|
||||
return await api.get<types.network.NetworkResource[]>('/networks', opts)
|
||||
export class Network {
|
||||
constructor(public api: DockerApiClient) {
|
||||
}
|
||||
list(opts?: opts.network.ListOpts) {
|
||||
return this.api.get<types.network.NetworkResource[]>('/networks', opts)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
import * as api from '../utils/api'
|
||||
import * as types from '../api/types'
|
||||
import { DockerApiClient } from './api';
|
||||
|
||||
export namespace node {
|
||||
export async function list() {
|
||||
return await api.get<types.node.Node[]>('/nodes');
|
||||
export class Node {
|
||||
constructor(public api: DockerApiClient) {
|
||||
}
|
||||
list() {
|
||||
return this.api.get<types.node.Node[]>('/nodes');
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,27 @@
|
||||
import * as api from '../utils/api';
|
||||
import * as opts from '../api/opts';
|
||||
import * as types from '../api/types';
|
||||
import * as filterUtil from '../api/opts/filter'
|
||||
import * as http from 'http'
|
||||
import { DockerApiClient } from './api';
|
||||
|
||||
export namespace service {
|
||||
export async function list(filter?: opts.service.FilterOpt) {
|
||||
return await api.get<types.service.Service[]>('/services', {
|
||||
export class Service {
|
||||
constructor(public api: DockerApiClient) {
|
||||
}
|
||||
async list(filter?: opts.service.FilterOpt) {
|
||||
return await this.api.get<types.service.Service[]>('/services', {
|
||||
filters: filterUtil.toJSON(filter)
|
||||
});
|
||||
}
|
||||
export async function create() {
|
||||
async create() {
|
||||
|
||||
}
|
||||
export async function inspect(id: string, query: { insertDefaults: boolean } = { insertDefaults: false }) {
|
||||
return await api.get<types.service.Service>(`/services/${id}`, query);
|
||||
async inspect(id: string, query: { insertDefaults: boolean } = { insertDefaults: false }) {
|
||||
return await this.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)
|
||||
async update(id: string, query: { version: number, registryAuthFrom?: string, rollback?: string }, data: any) {
|
||||
return await this.api.post<any>(this.api.getUri(`/services/${id}/update`, query), data)
|
||||
}
|
||||
export async function logs(id: string, opts: opts.service.LogsOpts = {}): Promise<http.ServerResponse> {
|
||||
async logs(id: string, opts: opts.service.LogsOpts = {}): Promise<http.ServerResponse> {
|
||||
let data = {
|
||||
follow: true,
|
||||
stdout: true,
|
||||
@ -27,6 +29,6 @@ export namespace service {
|
||||
tail: 10,
|
||||
...opts
|
||||
}
|
||||
return await api.stream(`/services/${id}/logs`, data);
|
||||
return await this.api.stream(`/services/${id}/logs`, data);
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,26 @@
|
||||
import * as api from '../utils/api'
|
||||
import * as opts from '../api/opts'
|
||||
import * as types from '../api/types'
|
||||
import { DockerApiClient } from './api';
|
||||
|
||||
export namespace swarm {
|
||||
export async function inspect() {
|
||||
return await api.get<types.swarm.Info>('/swarm');
|
||||
export class Swarm {
|
||||
constructor(public client: DockerApiClient) {
|
||||
}
|
||||
|
||||
export async function init(opts: opts.swarm.InitOpts) {
|
||||
return await api.post<string>('/swarm/init', opts);
|
||||
inspect() {
|
||||
return this.client.get<types.swarm.Info>('/swarm');
|
||||
}
|
||||
|
||||
export async function join(opts: opts.swarm.JoinOpts) {
|
||||
return await api.post<string>('/swarm/join', opts);
|
||||
init(opts: opts.swarm.InitOpts) {
|
||||
return this.client.post<string>('/swarm/init', opts);
|
||||
}
|
||||
|
||||
export async function leave(force: boolean = false) {
|
||||
return await api.post<string>(`/swarm/leave?force=${force}`);
|
||||
join(opts: opts.swarm.JoinOpts) {
|
||||
return this.client.post<string>('/swarm/join', opts);
|
||||
}
|
||||
|
||||
export async function unlockkey() {
|
||||
return await api.get<string>(`/swarm/unlockkey`);
|
||||
leave(force: boolean = false) {
|
||||
return this.client.post<string>(`/swarm/leave?force=${force}`);
|
||||
}
|
||||
|
||||
export async function unlock(opts: opts.swarm.UnlockOpts) {
|
||||
return await api.post<string>(`/swarm/unlockkey`, opts);
|
||||
unlockkey() {
|
||||
return this.client.get<string>(`/swarm/unlockkey`);
|
||||
}
|
||||
unlock(opts: opts.swarm.UnlockOpts) {
|
||||
return this.client.post<string>(`/swarm/unlockkey`, opts);
|
||||
}
|
||||
}
|
@ -1,16 +1,18 @@
|
||||
import * as api from '../utils/api'
|
||||
import * as types from '../api/types'
|
||||
import { DockerApiClient } from './api';
|
||||
|
||||
export namespace system {
|
||||
export async function info() {
|
||||
return await api.get<types.system.Info>('/info');
|
||||
export class System {
|
||||
constructor(public api: DockerApiClient) {
|
||||
}
|
||||
info() {
|
||||
return this.api.get<types.system.Info>('/info');
|
||||
}
|
||||
|
||||
export async function version() {
|
||||
return await api.get<types.system.Version>('/version');
|
||||
version() {
|
||||
return this.api.get<types.system.Version>('/version');
|
||||
}
|
||||
|
||||
export async function events() {
|
||||
return await api.stream('/events');
|
||||
events() {
|
||||
return this.api.stream('/events');
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,22 @@
|
||||
import * as api from '../utils/api'
|
||||
import * as opts from '../api/opts'
|
||||
import * as types from '../api/types'
|
||||
import * as http from 'http'
|
||||
import { DockerApiClient } from './api';
|
||||
|
||||
export namespace task {
|
||||
export async function list() {
|
||||
return await api.get<types.task.Task[]>('/tasks');
|
||||
export class Task {
|
||||
constructor(public api: DockerApiClient) {
|
||||
}
|
||||
list() {
|
||||
return this.api.get<types.task.Task[]>('/tasks');
|
||||
}
|
||||
logs(id: string, opts: opts.task.LogsOpts = {}): Promise<http.ServerResponse> {
|
||||
let data = {
|
||||
follow: true,
|
||||
stdout: true,
|
||||
stderr: true,
|
||||
tail: 10,
|
||||
...opts
|
||||
}
|
||||
return this.api.stream(`/services/${id}/logs`, data);
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
import * as api from '../utils/api'
|
||||
import * as types from '../api/types'
|
||||
import { DockerApiClient } from './api';
|
||||
|
||||
export namespace volume {
|
||||
export async function list() {
|
||||
return await api.get<types.volume.VolumeJSON>('/volumes');
|
||||
export class Volume {
|
||||
constructor(public api: DockerApiClient) {
|
||||
}
|
||||
list() {
|
||||
return this.api.get<types.volume.VolumeJSON>('/volumes');
|
||||
}
|
||||
}
|
@ -1 +1,2 @@
|
||||
export * from './client'
|
||||
import client from './client'
|
||||
export default client;
|
@ -1,5 +1,5 @@
|
||||
import * as http from 'http'
|
||||
import axios, { AxiosResponse, AxiosRequestConfig, Method, AxiosInstance } from 'axios'
|
||||
import { AxiosResponse, AxiosRequestConfig, Method, AxiosInstance } from 'axios'
|
||||
|
||||
let api: AxiosInstance;
|
||||
|
||||
@ -66,19 +66,3 @@ HANDLE TIME : ${Date.now() - startTime}ms
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
const instanceConfig: AxiosRequestConfig = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
if (process.env.DOCKER_HOST.startsWith("/")) {
|
||||
instanceConfig.socketPath = process.env.DOCKER_HOST
|
||||
} else {
|
||||
instanceConfig.baseURL = process.env.DOCKER_HOST
|
||||
}
|
||||
api = axios.create(instanceConfig)
|
||||
}
|
||||
|
||||
init();
|
||||
|
Loading…
Reference in New Issue
Block a user