2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 16:10:59 +08:00

feat: 容器部分

This commit is contained in:
耗子
2024-03-16 00:15:37 +08:00
parent ccd0aa3505
commit db0e722ea3
9 changed files with 715 additions and 24 deletions

View File

@@ -1,19 +1,384 @@
package controllers
import (
"fmt"
"strconv"
"strings"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/docker/go-connections/nat"
"github.com/goravel/framework/contracts/http"
requests "panel/app/http/requests/container"
"panel/internal/services"
)
type ContainerController struct {
// Dependent services
container services.Container
}
func NewContainerController() *ContainerController {
return &ContainerController{
// Inject services
container: services.NewContainer(),
}
}
func (r *ContainerController) Index(ctx http.Context) http.Response {
return nil
func (r *ContainerController) ContainerList(ctx http.Context) http.Response {
containers, err := r.container.ContainerListAll()
if err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, containers)
}
func (r *ContainerController) ContainerSearch(ctx http.Context) http.Response {
fields := strings.Fields(ctx.Request().Query("names"))
containers, err := r.container.ContainerListByNames(fields)
if err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, containers)
}
func (r *ContainerController) ContainerCreate(ctx http.Context) http.Response {
var request requests.ContainerCreate
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
var hostConf container.HostConfig
var networkConf network.NetworkingConfig
portMap := make(nat.PortMap)
for _, port := range request.Ports {
if port.ContainerStart-port.ContainerEnd != port.HostStart-port.HostEnd {
return Error(ctx, http.StatusUnprocessableEntity, fmt.Sprintf("容器端口和主机端口数量不匹配(容器: %d 主机: %d", port.ContainerStart-port.ContainerEnd, port.HostStart-port.HostEnd))
}
if port.ContainerStart > port.ContainerEnd || port.HostStart > port.HostEnd || port.ContainerStart < 1 || port.HostStart < 1 {
return Error(ctx, http.StatusUnprocessableEntity, "端口范围不正确")
}
count := 0
for host := port.HostStart; host <= port.HostEnd; host++ {
bindItem := nat.PortBinding{HostPort: strconv.Itoa(host), HostIP: port.Host}
portMap[nat.Port(fmt.Sprintf("%d/%s", port.ContainerStart+count, port.Protocol))] = []nat.PortBinding{bindItem}
count++
}
}
exposed := make(nat.PortSet)
for port := range portMap {
exposed[port] = struct{}{}
}
if request.Network != "" {
switch request.Network {
case "host", "none", "bridge":
hostConf.NetworkMode = container.NetworkMode(request.Network)
}
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{request.Network: {}}
} else {
networkConf = network.NetworkingConfig{}
}
hostConf.Privileged = request.Privileged
hostConf.AutoRemove = request.AutoRemove
hostConf.CPUShares = request.CPUShares
hostConf.PublishAllPorts = request.PublishAllPorts
hostConf.RestartPolicy = container.RestartPolicy{Name: container.RestartPolicyMode(request.RestartPolicy)}
if request.RestartPolicy == "on-failure" {
hostConf.RestartPolicy.MaximumRetryCount = 5
}
hostConf.NanoCPUs = request.CPUs * 1000000000
hostConf.Memory = request.Memory * 1024 * 1024
hostConf.MemorySwap = 0
hostConf.PortBindings = portMap
hostConf.Binds = []string{}
volumes := make(map[string]struct{})
for _, volume := range request.Volumes {
volumes[volume.Container] = struct{}{}
hostConf.Binds = append(hostConf.Binds, fmt.Sprintf("%s:%s:%s", volume.Host, volume.Container, volume.Mode))
}
id, err := r.container.ContainerCreate(request.Name,
container.Config{
Image: request.Image,
Env: request.Env,
Entrypoint: request.Entrypoint,
Cmd: request.Command,
Labels: r.container.SliceToMap(request.Labels),
ExposedPorts: exposed,
OpenStdin: request.OpenStdin,
Tty: request.Tty,
Volumes: volumes,
},
hostConf,
networkConf,
)
if err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, id)
}
func (r *ContainerController) ContainerRemove(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
if err := r.container.ContainerRemove(request.ID); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, nil)
}
func (r *ContainerController) ContainerStart(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
if err := r.container.ContainerStart(request.ID); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, nil)
}
func (r *ContainerController) ContainerStop(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
if err := r.container.ContainerStop(request.ID); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, nil)
}
func (r *ContainerController) ContainerRestart(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
if err := r.container.ContainerRestart(request.ID); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, nil)
}
func (r *ContainerController) ContainerPause(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
if err := r.container.ContainerPause(request.ID); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, nil)
}
func (r *ContainerController) ContainerUnpause(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
if err := r.container.ContainerUnpause(request.ID); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, nil)
}
func (r *ContainerController) ContainerInspect(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
data, err := r.container.ContainerInspect(request.ID)
if err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, data)
}
func (r *ContainerController) ContainerKill(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
if err := r.container.ContainerKill(request.ID); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, nil)
}
func (r *ContainerController) ContainerRename(ctx http.Context) http.Response {
var request requests.ContainerRename
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
if err := r.container.ContainerRename(request.ID, request.Name); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, nil)
}
func (r *ContainerController) ContainerStats(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
data, err := r.container.ContainerStats(request.ID)
if err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, data)
}
func (r *ContainerController) ContainerExist(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
exist, err := r.container.ContainerExist(request.ID)
if err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, exist)
}
func (r *ContainerController) ContainerLogs(ctx http.Context) http.Response {
var request requests.ID
if sanitize := Sanitize(ctx, &request); sanitize != nil {
return sanitize
}
data, err := r.container.ContainerLogs(request.ID)
if err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, data)
}
func (r *ContainerController) ContainerPrune(ctx http.Context) http.Response {
if err := r.container.ContainerPrune(); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, nil)
}
func (r *ContainerController) NetworkList(ctx http.Context) http.Response {
networks, err := r.container.NetworkList()
if err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, networks)
}
func (r *ContainerController) NetworkCreate(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) NetworkRemove(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) NetworkExist(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) NetworkInspect(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) NetworkConnect(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) NetworkDisconnect(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) NetworkPrune(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) ImageList(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) ImageExist(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) ImagePull(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) ImageRemove(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) ImagePrune(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) ImageInspect(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) VolumeList(ctx http.Context) http.Response {
volumes, err := r.container.VolumeList()
if err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, volumes)
}
func (r *ContainerController) VolumeCreate(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) VolumeExist(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) VolumeInspect(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) VolumeRemove(ctx http.Context) http.Response {
return Success(ctx, nil)
}
func (r *ContainerController) VolumePrune(ctx http.Context) http.Response {
return Success(ctx, nil)
}

View File

@@ -0,0 +1,66 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type ContainerCreate struct {
Name string `form:"name" json:"name"`
Image string `form:"image" json:"image"`
Ports []ContainerPort `form:"ports" json:"ports"`
Network string `form:"network" json:"network"`
Volumes []ContainerVolume `form:"volumes" json:"volumes"`
Labels []string `form:"labels" json:"labels"`
Env []string `form:"env" json:"env"`
Entrypoint []string `form:"entrypoint" json:"entrypoint"`
Command []string `form:"command" json:"command"`
RestartPolicy string `form:"restart_policy" json:"restart_policy"`
AutoRemove bool `form:"auto_remove" json:"auto_remove"`
Privileged bool `form:"privileged" json:"privileged"`
OpenStdin bool `form:"openStdin" json:"open_stdin"`
PublishAllPorts bool `form:"publish_all_ports" json:"publish_all_ports"`
Tty bool `form:"tty" json:"tty"`
CPUShares int64 `form:"cpu_shares" json:"cpu_shares"`
CPUs int64 `form:"cpus" json:"cpus"`
Memory int64 `form:"memory" json:"memory"`
}
func (r *ContainerCreate) Authorize(ctx http.Context) error {
return nil
}
func (r *ContainerCreate) Rules(ctx http.Context) map[string]string {
return map[string]string{
"name": "required|string",
"image": "required|string",
"ports": "slice",
"network": "string",
"volumes": "slice",
"labels": "slice",
"env": "slice",
"entrypoint": "slice",
"command": "slice",
"restart_policy": "string|in:always,on-failure,unless-stopped,no",
"auto_remove": "bool",
"privileged": "bool",
"open_stdin": "bool",
"publish_all_ports": "bool",
"tty": "bool",
"cpu_shares": "int",
"cpus": "int",
"memory": "int",
}
}
func (r *ContainerCreate) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *ContainerCreate) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *ContainerCreate) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,34 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type ContainerRename struct {
ID string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
}
func (r *ContainerRename) Authorize(ctx http.Context) error {
return nil
}
func (r *ContainerRename) Rules(ctx http.Context) map[string]string {
return map[string]string{
"id": "required|string",
"name": "required|string",
}
}
func (r *ContainerRename) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *ContainerRename) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *ContainerRename) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,68 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type ContainerUpdate struct {
ID string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
Image string `form:"image" json:"image"`
Ports []ContainerPort `form:"ports" json:"ports"`
Network string `form:"network" json:"network"`
Volumes []ContainerVolume `form:"volumes" json:"volumes"`
Labels []string `form:"labels" json:"labels"`
Env []string `form:"env" json:"env"`
Entrypoint []string `form:"entrypoint" json:"entrypoint"`
Command []string `form:"command" json:"command"`
RestartPolicy string `form:"restart_policy" json:"restart_policy"`
AutoRemove bool `form:"auto_remove" json:"auto_remove"`
Privileged bool `form:"privileged" json:"privileged"`
OpenStdin bool `form:"openStdin" json:"open_stdin"`
PublishAllPorts bool `form:"publish_all_ports" json:"publish_all_ports"`
Tty bool `form:"tty" json:"tty"`
CPUShares int64 `form:"cpu_shares" json:"cpu_shares"`
CPUs int64 `form:"cpus" json:"cpus"`
Memory int64 `form:"memory" json:"memory"`
}
func (r *ContainerUpdate) Authorize(ctx http.Context) error {
return nil
}
func (r *ContainerUpdate) Rules(ctx http.Context) map[string]string {
return map[string]string{
"id": "required|string",
"name": "required|string",
"image": "required|string",
"ports": "slice",
"network": "string",
"volumes": "slice",
"labels": "slice",
"env": "slice",
"entrypoint": "slice",
"command": "slice",
"restart_policy": "string|in:always,on-failure,unless-stopped,no",
"auto_remove": "bool",
"privileged": "bool",
"open_stdin": "bool",
"publish_all_ports": "bool",
"tty": "bool",
"cpu_shares": "int",
"cpus": "int",
"memory": "int",
}
}
func (r *ContainerUpdate) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *ContainerUpdate) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *ContainerUpdate) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,32 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type ID struct {
ID string `form:"id" json:"id"`
}
func (r *ID) Authorize(ctx http.Context) error {
return nil
}
func (r *ID) Rules(ctx http.Context) map[string]string {
return map[string]string{
"id": "required|string",
}
}
func (r *ID) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *ID) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *ID) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,16 @@
package requests
type ContainerPort struct {
ContainerStart int `json:"start"`
ContainerEnd int `json:"end"`
Host string `json:"host"`
HostStart int `json:"hostStart"`
HostEnd int `json:"hostEnd"`
Protocol string `json:"protocol"`
}
type ContainerVolume struct {
Host string `json:"host"`
Container string `json:"container"`
Mode string `json:"mode"`
}

View File

@@ -1 +1,50 @@
package internal
import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/volume"
)
type Container interface {
ContainerListAll() ([]types.Container, error)
ContainerListByNames(names []string) ([]types.Container, error)
ContainerCreate(name string, config container.Config, host container.HostConfig, networkConfig network.NetworkingConfig) (string, error)
ContainerRemove(id string) error
ContainerStart(id string) error
ContainerStop(id string) error
ContainerRestart(id string) error
ContainerPause(id string) error
ContainerUnpause(id string) error
ContainerInspect(id string) (types.ContainerJSON, error)
ContainerKill(id string) error
ContainerRename(id string, newName string) error
ContainerStats(id string) (types.ContainerStats, error)
ContainerExist(name string) (bool, error)
ContainerUpdate(id string, config container.UpdateConfig) error
ContainerLogs(id string) (string, error)
ContainerPrune() error
NetworkList() ([]types.NetworkResource, error)
NetworkCreate(name string) error
NetworkRemove(id string) error
NetworkExist(name string) (bool, error)
NetworkInspect(id string) (types.NetworkResource, error)
NetworkConnect(networkID string, containerID string) error
NetworkDisconnect(networkID string, containerID string) error
NetworkPrune() error
ImageList() ([]image.Summary, error)
ImageExist(reference string) (bool, error)
ImagePull(reference string) error
ImageRemove(imageID string) error
ImagePrune() error
ImageInspect(imageID string) (types.ImageInspect, error)
VolumeList() ([]*volume.Volume, error)
VolumeCreate(name string, options, labels map[string]string) (volume.Volume, error)
VolumeExist(name string) (bool, error)
VolumeInspect(volumeID string) (volume.Volume, error)
VolumeRemove(volumeID string) error
VolumePrune() error
SliceToMap(slice []string) map[string]string
}

View File

@@ -3,6 +3,7 @@ package services
import (
"context"
"io"
"strings"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
@@ -17,12 +18,12 @@ type Container struct {
client *client.Client
}
func NewContainer(sock ...string) *Container {
func NewContainer(sock ...string) Container {
if len(sock) == 0 {
sock[0] = "/run/podman/podman.sock"
}
cli, _ := client.NewClientWithOpts(client.WithHost("unix://"+sock[0]), client.WithAPIVersionNegotiation())
return &Container{
return Container{
client: cli,
}
}
@@ -81,6 +82,11 @@ func (r *Container) ContainerStop(id string) error {
return r.client.ContainerStop(context.Background(), id, container.StopOptions{})
}
// ContainerRestart 重启容器
func (r *Container) ContainerRestart(id string) error {
return r.client.ContainerRestart(context.Background(), id, container.StopOptions{})
}
// ContainerPause 暂停容器
func (r *Container) ContainerPause(id string) error {
return r.client.ContainerPause(context.Background(), id)
@@ -111,8 +117,8 @@ func (r *Container) ContainerStats(id string) (types.ContainerStats, error) {
return r.client.ContainerStats(context.Background(), id, false)
}
// ContainerExists 判断容器是否存在
func (r *Container) ContainerExists(name string) (bool, error) {
// ContainerExist 判断容器是否存在
func (r *Container) ContainerExist(name string) (bool, error) {
var options container.ListOptions
options.Filters = filters.NewArgs(filters.Arg("name", name))
containers, err := r.client.ContainerList(context.Background(), options)
@@ -155,11 +161,6 @@ func (r *Container) ContainerPrune() error {
return err
}
// ContainerRestart 重启容器
func (r *Container) ContainerRestart(id string) error {
return r.client.ContainerRestart(context.Background(), id, container.StopOptions{})
}
// NetworkList 列出网络
func (r *Container) NetworkList() ([]types.NetworkResource, error) {
return r.client.NetworkList(context.Background(), types.NetworkListOptions{})
@@ -174,6 +175,11 @@ func (r *Container) NetworkCreate(name string) error {
return err
}
// NetworkRemove 删除网络
func (r *Container) NetworkRemove(id string) error {
return r.client.NetworkRemove(context.Background(), id)
}
// NetworkExist 判断网络是否存在
func (r *Container) NetworkExist(name string) (bool, error) {
var options types.NetworkListOptions
@@ -207,11 +213,6 @@ func (r *Container) NetworkPrune() error {
return err
}
// NetworkRemove 删除网络
func (r *Container) NetworkRemove(id string) error {
return r.client.NetworkRemove(context.Background(), id)
}
// ImageList 列出镜像
func (r *Container) ImageList() ([]image.Summary, error) {
return r.client.ImageList(context.Background(), types.ImageListOptions{
@@ -258,6 +259,12 @@ func (r *Container) ImageInspect(id string) (types.ImageInspect, error) {
return img, err
}
// VolumeList 列出存储卷
func (r *Container) VolumeList() ([]*volume.Volume, error) {
volumes, err := r.client.VolumeList(context.Background(), volume.ListOptions{})
return volumes.Volumes, err
}
// VolumeCreate 创建存储卷
func (r *Container) VolumeCreate(name string, options, labels map[string]string) (volume.Volume, error) {
return r.client.VolumeCreate(context.Background(), volume.CreateOptions{
@@ -268,12 +275,6 @@ func (r *Container) VolumeCreate(name string, options, labels map[string]string)
})
}
// VolumeList 列出存储卷
func (r *Container) VolumeList() ([]*volume.Volume, error) {
volumes, err := r.client.VolumeList(context.Background(), volume.ListOptions{})
return volumes.Volumes, err
}
// VolumeExist 判断存储卷是否存在
func (r *Container) VolumeExist(name string) (bool, error) {
var options volume.ListOptions
@@ -301,3 +302,15 @@ func (r *Container) VolumePrune() error {
_, err := r.client.VolumesPrune(context.Background(), filters.NewArgs())
return err
}
// SliceToMap 将切片转换为 map
func (r *Container) SliceToMap(slice []string) map[string]string {
m := make(map[string]string)
for _, s := range slice {
if strings.Contains(s, "=") {
sps := strings.SplitN(s, "=", 2)
m[sps[0]] = sps[1]
}
}
return m
}

View File

@@ -113,6 +113,54 @@ func Api() {
r.Get("pingStatus", safeController.GetPingStatus)
r.Post("pingStatus", safeController.SetPingStatus)
})
r.Prefix("container").Middleware(middleware.Jwt()).Group(func(r route.Router) {
containerController := controllers.NewContainerController()
r.Get("list", containerController.ContainerList)
r.Get("search", containerController.ContainerSearch)
r.Post("create", containerController.ContainerCreate)
r.Post("remove", containerController.ContainerRemove)
r.Post("start", containerController.ContainerStart)
r.Post("stop", containerController.ContainerStop)
r.Post("restart", containerController.ContainerRestart)
r.Post("pause", containerController.ContainerPause)
r.Post("unpause", containerController.ContainerUnpause)
r.Get("inspect", containerController.ContainerInspect)
r.Post("kill", containerController.ContainerKill)
r.Post("rename", containerController.ContainerRename)
r.Get("stats", containerController.ContainerStats)
r.Post("exist", containerController.ContainerExist)
r.Get("logs", containerController.ContainerLogs)
r.Post("prune", containerController.ContainerPrune)
r.Prefix("network").Group(func(r route.Router) {
r.Get("list", containerController.NetworkList)
r.Post("create", containerController.NetworkCreate)
r.Post("remove", containerController.NetworkRemove)
r.Post("exist", containerController.NetworkExist)
r.Get("inspect", containerController.NetworkInspect)
r.Post("connect", containerController.NetworkConnect)
r.Post("disconnect", containerController.NetworkDisconnect)
r.Post("prune", containerController.NetworkPrune)
})
r.Prefix("image").Group(func(r route.Router) {
r.Get("list", containerController.ImageList)
r.Post("exist", containerController.ImageExist)
r.Post("pull", containerController.ImagePull)
r.Post("remove", containerController.ImageRemove)
r.Post("prune", containerController.ImagePrune)
r.Get("inspect", containerController.ImageInspect)
})
r.Prefix("volume").Group(func(r route.Router) {
r.Get("list", containerController.VolumeList)
r.Post("create", containerController.VolumeCreate)
r.Post("exist", containerController.VolumeExist)
r.Get("inspect", containerController.VolumeInspect)
r.Post("remove", containerController.VolumeRemove)
r.Post("prune", containerController.VolumePrune)
})
})
r.Prefix("file").Middleware(middleware.Jwt()).Group(func(r route.Router) {
fileController := controllers.NewFileController()
r.Post("create", fileController.Create)