Skip to content

Commit

Permalink
Add docker disk usage and image prune endpoints
Browse files Browse the repository at this point in the history
* Add Docker disk usage endpoint at /api/system/docker/disk (GET)
* Add image prune endpoint at /api/system/docker/image/prune (DELETE)
  • Loading branch information
iamkubi authored Apr 18, 2024
1 parent 12ac06d commit cd546ba
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 3 deletions.
10 changes: 10 additions & 0 deletions environment/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,13 @@ func createDockerNetwork(ctx context.Context, cli *client.Client) error {
}
return nil
}

// Gets usage statistics for the Docker Daemon such as disk usage
func GetDockerUsage(ctx context.Context) (types.DiskUsage, error) {
cli, err := Docker()
if err != nil {
return types.DiskUsage{}, err
}
disk, err := cli.DiskUsage(ctx, types.DiskUsageOptions{})
return disk, err
}
6 changes: 3 additions & 3 deletions router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"emperror.dev/errors"
"github.com/apex/log"
"github.com/gin-gonic/gin"

"github.com/pelican-dev/wings/config"
"github.com/pelican-dev/wings/remote"
"github.com/pelican-dev/wings/router/middleware"
Expand Down Expand Up @@ -53,13 +52,14 @@ func Configure(m *wserver.Manager, client remote.Client) *gin.Engine {
// This request does not need the AuthorizationMiddleware as the panel should never call it
// and requests are authenticated through a JWT the panel issues to the other daemon.
router.POST("/api/transfers", postTransfers)

// All the routes beyond this mount will use an authorization middleware
// and will not be accessible without the correct Authorization header provided.
protected := router.Use(middleware.RequireAuthorization())
protected.POST("/api/update", postUpdateConfiguration)

protected.GET("/api/system", getSystemInformation)
protected.GET("/api/system/docker/disk", getDockerDiskUsage)
protected.DELETE("/api/system/docker/image/prune", pruneDockerImages)
protected.GET("/api/system/ips", getSystemIps)
protected.GET("/api/system/utilization", getSystemUtilization)
protected.GET("/api/servers", getAllServers)
Expand Down
20 changes: 20 additions & 0 deletions router/router_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,26 @@ func getSystemUtilization(c *gin.Context) {
c.JSON(http.StatusOK, u)
}

// Returns docker disk utilization
func getDockerDiskUsage(c *gin.Context) {
d, err := system.GetDockerDiskUsage(c)
if err != nil {
middleware.CaptureAndAbort(c, err)
return
}
c.JSON(http.StatusOK, d)
}

// Prunes the docker image cache
func pruneDockerImages(c *gin.Context) {
p, err := system.PruneDockerImages(c)
if err != nil {
middleware.CaptureAndAbort(c, err)
return
}
c.JSON(http.StatusOK, p)
}

// Returns all the servers that are registered and configured correctly on
// this wings instance.
func getAllServers(c *gin.Context) {
Expand Down
65 changes: 65 additions & 0 deletions system/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package system

import (
"context"
"github.com/docker/docker/api/types/filters"
"net"
"runtime"

Expand Down Expand Up @@ -77,6 +78,14 @@ type Utilization struct {
DiskUsed uint64 `json:"disk_used"`
}

type DockerDiskUsage struct {
ContainersSize int64 `json:"containers_size"`
ImagesTotal int `json:"images_total"`
ImagesActive int64 `json:"images_active"`
ImagesSize int64 `json:"images_size"`
BuildCacheSize int64 `json:"build_cache_size"`
}

func GetSystemInformation() (*Information, error) {
k, err := kernel.GetKernelVersion()
if err != nil {
Expand Down Expand Up @@ -195,6 +204,62 @@ func GetSystemUtilization() (*Utilization, error) {
}, nil
}

func GetDockerDiskUsage(ctx context.Context) (*DockerDiskUsage, error) {
// TODO: find a way to re-use the client from the docker environment.
c, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return &DockerDiskUsage{}, err
}
defer c.Close()

d, err := c.DiskUsage(ctx, types.DiskUsageOptions{})
if err != nil {
return &DockerDiskUsage{}, err
}

var bcs int64
for _, bc := range d.BuildCache {
if !bc.Shared {
bcs += bc.Size
}
}

var a int64
for _, i := range d.Images {
if i.Containers > 0 {
a++
}
}

var cs int64
for _, b := range d.Containers {
cs += b.SizeRootFs
}

return &DockerDiskUsage{
ImagesTotal: len(d.Images),
ImagesActive: a,
ImagesSize: int64(d.LayersSize),
ContainersSize: int64(cs),
BuildCacheSize: bcs,
}, nil
}

func PruneDockerImages(ctx context.Context) (types.ImagesPruneReport, error) {
// TODO: find a way to re-use the client from the docker environment.
c, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return types.ImagesPruneReport{}, err
}
defer c.Close()

prune, err := c.ImagesPrune(ctx, filters.Args{})
if err != nil {
return types.ImagesPruneReport{}, err
}
return prune, nil
}

func GetDockerInfo(ctx context.Context) (types.Version, system.Info, error) {
// TODO: find a way to re-use the client from the docker environment.
c, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
Expand Down

0 comments on commit cd546ba

Please sign in to comment.