mirror of
https://github.com/yusing/godoxy.git
synced 2025-05-20 12:42:34 +02:00
refactor docker api code, deps upgrade
This commit is contained in:
parent
e22366e524
commit
05d2f77c0c
6 changed files with 73 additions and 79 deletions
10
go.mod
10
go.mod
|
@ -6,8 +6,8 @@ require (
|
||||||
github.com/PuerkitoBio/goquery v1.10.2 // parsing HTML for extract fav icon
|
github.com/PuerkitoBio/goquery v1.10.2 // parsing HTML for extract fav icon
|
||||||
github.com/coder/websocket v1.8.12 // websocket for API and agent
|
github.com/coder/websocket v1.8.12 // websocket for API and agent
|
||||||
github.com/coreos/go-oidc/v3 v3.12.0 // oidc authentication
|
github.com/coreos/go-oidc/v3 v3.12.0 // oidc authentication
|
||||||
github.com/docker/cli v27.5.1+incompatible // docker CLI
|
github.com/docker/cli v28.0.0+incompatible // docker CLI
|
||||||
github.com/docker/docker v27.5.1+incompatible // docker daemon
|
github.com/docker/docker v28.0.0+incompatible // docker daemon
|
||||||
github.com/fsnotify/fsnotify v1.8.0 // file watcher
|
github.com/fsnotify/fsnotify v1.8.0 // file watcher
|
||||||
github.com/go-acme/lego/v4 v4.22.2 // acme client
|
github.com/go-acme/lego/v4 v4.22.2 // acme client
|
||||||
github.com/go-playground/validator/v10 v10.25.0 // validator
|
github.com/go-playground/validator/v10 v10.25.0 // validator
|
||||||
|
@ -15,9 +15,10 @@ require (
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1 // jwt for default auth
|
github.com/golang-jwt/jwt/v5 v5.2.1 // jwt for default auth
|
||||||
github.com/gotify/server/v2 v2.6.1 // reference the Message struct for json response
|
github.com/gotify/server/v2 v2.6.1 // reference the Message struct for json response
|
||||||
github.com/lithammer/fuzzysearch v1.1.8 // fuzzy search for searching icons and filtering metrics
|
github.com/lithammer/fuzzysearch v1.1.8 // fuzzy search for searching icons and filtering metrics
|
||||||
github.com/prometheus/client_golang v1.20.5 // metrics
|
github.com/prometheus/client_golang v1.21.0 // metrics
|
||||||
github.com/puzpuzpuz/xsync/v3 v3.5.1 // lock free map for concurrent operations
|
github.com/puzpuzpuz/xsync/v3 v3.5.1 // lock free map for concurrent operations
|
||||||
github.com/rs/zerolog v1.33.0 // logging
|
github.com/rs/zerolog v1.33.0 // logging
|
||||||
|
github.com/shirou/gopsutil/v4 v4.25.1 // system info metrics
|
||||||
github.com/vincent-petithory/dataurl v1.0.0 // data url for fav icon
|
github.com/vincent-petithory/dataurl v1.0.0 // data url for fav icon
|
||||||
golang.org/x/crypto v0.33.0 // encrypting password with bcrypt
|
golang.org/x/crypto v0.33.0 // encrypting password with bcrypt
|
||||||
golang.org/x/net v0.35.0 // HTTP header utilities
|
golang.org/x/net v0.35.0 // HTTP header utilities
|
||||||
|
@ -25,7 +26,6 @@ require (
|
||||||
golang.org/x/text v0.22.0 // string utilities
|
golang.org/x/text v0.22.0 // string utilities
|
||||||
golang.org/x/time v0.10.0 // time utilities
|
golang.org/x/time v0.10.0 // time utilities
|
||||||
gopkg.in/yaml.v3 v3.0.1 // yaml parsing for different config files
|
gopkg.in/yaml.v3 v3.0.1 // yaml parsing for different config files
|
||||||
github.com/shirou/gopsutil/v4 v4.25.1 // system info metrics
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -51,7 +51,7 @@ require (
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
|
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
|
|
16
go.sum
16
go.sum
|
@ -27,10 +27,10 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
github.com/docker/cli v27.5.1+incompatible h1:JB9cieUT9YNiMITtIsguaN55PLOHhBSz3LKVc6cqWaY=
|
github.com/docker/cli v28.0.0+incompatible h1:ido37VmLUqEp+5NFb9icd6BuBB+SNDgCn+5kPCr2buA=
|
||||||
github.com/docker/cli v27.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v28.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/docker v27.5.1+incompatible h1:4PYU5dnBYqRQi0294d1FBECqT9ECWeQAIfE8q4YnPY8=
|
github.com/docker/docker v28.0.0+incompatible h1:Olh0KS820sJ7nPsBKChVhk5pzqcwDR15fumfAd/p9hM=
|
||||||
github.com/docker/docker v27.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v28.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
|
@ -87,8 +87,8 @@ github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nu
|
||||||
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
|
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
@ -135,8 +135,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA=
|
||||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||||
|
|
|
@ -89,7 +89,7 @@ func NewHandler(cfg config.ConfigInstance) http.Handler {
|
||||||
mux.HandleFunc("GET", "/v1/metrics/uptime", uptime.Poller.ServeHTTP, true)
|
mux.HandleFunc("GET", "/v1/metrics/uptime", uptime.Poller.ServeHTTP, true)
|
||||||
mux.HandleFunc("GET", "/v1/cert/info", certapi.GetCertInfo, true)
|
mux.HandleFunc("GET", "/v1/cert/info", certapi.GetCertInfo, true)
|
||||||
mux.HandleFunc("", "/v1/cert/renew", certapi.RenewCert, true)
|
mux.HandleFunc("", "/v1/cert/renew", certapi.RenewCert, true)
|
||||||
mux.HandleFunc("GET", "/v1/docker/info", dockerapi.Info, true)
|
mux.HandleFunc("GET", "/v1/docker/info", dockerapi.DockerInfo, true)
|
||||||
mux.HandleFunc("GET", "/v1/docker/logs/{server}/{container}", dockerapi.Logs, true)
|
mux.HandleFunc("GET", "/v1/docker/logs/{server}/{container}", dockerapi.Logs, true)
|
||||||
mux.HandleFunc("GET", "/v1/docker/containers", dockerapi.Containers, true)
|
mux.HandleFunc("GET", "/v1/docker/containers", dockerapi.Containers, true)
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,9 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coder/websocket"
|
|
||||||
"github.com/coder/websocket/wsjson"
|
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/yusing/go-proxy/internal/gperr"
|
"github.com/yusing/go-proxy/internal/gperr"
|
||||||
"github.com/yusing/go-proxy/internal/net/gphttp/gpwebsocket"
|
|
||||||
"github.com/yusing/go-proxy/internal/net/gphttp/httpheaders"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Container struct {
|
type Container struct {
|
||||||
|
@ -23,30 +18,10 @@ type Container struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Containers(w http.ResponseWriter, r *http.Request) {
|
func Containers(w http.ResponseWriter, r *http.Request) {
|
||||||
if httpheaders.IsWebsocket(r.Header) {
|
serveHTTP[Container, []Container](w, r, GetContainers)
|
||||||
gpwebsocket.Periodic(w, r, 5*time.Second, func(conn *websocket.Conn) error {
|
|
||||||
containers, err := listContainers(r.Context())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return wsjson.Write(r.Context(), conn, containers)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
containers, err := listContainers(r.Context())
|
|
||||||
handleResult(w, err, containers)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func listContainers(ctx context.Context) ([]Container, error) {
|
func GetContainers(ctx context.Context, dockerClients DockerClients) ([]Container, gperr.Error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, reqTimeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
dockerClients, err := getDockerClients()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer closeAllClients(dockerClients)
|
|
||||||
|
|
||||||
errs := gperr.NewBuilder("failed to get containers")
|
errs := gperr.NewBuilder("failed to get containers")
|
||||||
containers := make([]Container, 0)
|
containers := make([]Container, 0)
|
||||||
for server, dockerClient := range dockerClients {
|
for server, dockerClient := range dockerClients {
|
||||||
|
|
|
@ -4,43 +4,39 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sort"
|
||||||
|
|
||||||
dockerSystem "github.com/docker/docker/api/types/system"
|
dockerSystem "github.com/docker/docker/api/types/system"
|
||||||
"github.com/yusing/go-proxy/internal/gperr"
|
"github.com/yusing/go-proxy/internal/gperr"
|
||||||
"github.com/yusing/go-proxy/internal/utils/strutils"
|
"github.com/yusing/go-proxy/internal/utils/strutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DockerInfo dockerSystem.Info
|
type dockerInfo dockerSystem.Info
|
||||||
|
|
||||||
func (d *DockerInfo) MarshalJSON() ([]byte, error) {
|
func (d *dockerInfo) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(map[string]any{
|
return json.Marshal(map[string]any{
|
||||||
"host": d.Name,
|
"name": d.Name,
|
||||||
|
"version": d.ServerVersion,
|
||||||
"containers": map[string]int{
|
"containers": map[string]int{
|
||||||
"total": d.Containers,
|
"total": d.Containers,
|
||||||
"running": d.ContainersRunning,
|
"running": d.ContainersRunning,
|
||||||
"paused": d.ContainersPaused,
|
"paused": d.ContainersPaused,
|
||||||
"stopped": d.ContainersStopped,
|
"stopped": d.ContainersStopped,
|
||||||
},
|
},
|
||||||
"images": d.Images,
|
"images": d.Images,
|
||||||
"n_cpu": d.NCPU,
|
"n_cpu": d.NCPU,
|
||||||
"memory": strutils.FormatByteSizeWithUnit(d.MemTotal),
|
"memory": strutils.FormatByteSizeWithUnit(d.MemTotal),
|
||||||
"version": d.ServerVersion,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Info(w http.ResponseWriter, r *http.Request) {
|
func DockerInfo(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx, cancel := context.WithTimeout(r.Context(), reqTimeout)
|
serveHTTP[dockerInfo, []dockerInfo](w, r, GetDockerInfo)
|
||||||
defer cancel()
|
}
|
||||||
|
|
||||||
dockerClients, ok := getDockerClientsWithErrHandling(w)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer closeAllClients(dockerClients)
|
|
||||||
|
|
||||||
|
func GetDockerInfo(ctx context.Context, dockerClients DockerClients) ([]dockerInfo, gperr.Error) {
|
||||||
errs := gperr.NewBuilder("failed to get docker info")
|
errs := gperr.NewBuilder("failed to get docker info")
|
||||||
|
dockerInfos := make([]dockerInfo, len(dockerClients))
|
||||||
|
|
||||||
dockerInfos := make([]DockerInfo, len(dockerClients))
|
|
||||||
i := 0
|
i := 0
|
||||||
for name, dockerClient := range dockerClients {
|
for name, dockerClient := range dockerClients {
|
||||||
info, err := dockerClient.Info(ctx)
|
info, err := dockerClient.Info(ctx)
|
||||||
|
@ -49,9 +45,12 @@ func Info(w http.ResponseWriter, r *http.Request) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
info.Name = name
|
info.Name = name
|
||||||
dockerInfos[i] = DockerInfo(info)
|
dockerInfos[i] = dockerInfo(info)
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
handleResult(w, errs.Error(), dockerInfos)
|
sort.Slice(dockerInfos, func(i, j int) bool {
|
||||||
|
return dockerInfos[i].Name < dockerInfos[j].Name
|
||||||
|
})
|
||||||
|
return dockerInfos, errs.Error()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
package dockerapi
|
package dockerapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/coder/websocket"
|
||||||
|
"github.com/coder/websocket/wsjson"
|
||||||
config "github.com/yusing/go-proxy/internal/config/types"
|
config "github.com/yusing/go-proxy/internal/config/types"
|
||||||
"github.com/yusing/go-proxy/internal/docker"
|
"github.com/yusing/go-proxy/internal/docker"
|
||||||
"github.com/yusing/go-proxy/internal/gperr"
|
"github.com/yusing/go-proxy/internal/gperr"
|
||||||
|
"github.com/yusing/go-proxy/internal/net/gphttp/gpwebsocket"
|
||||||
|
"github.com/yusing/go-proxy/internal/net/gphttp/httpheaders"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
DockerClients map[string]*docker.SharedClient
|
||||||
|
ResultType[T any] interface {
|
||||||
|
map[string]T | []T
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// getDockerClients returns a map of docker clients for the current config.
|
// getDockerClients returns a map of docker clients for the current config.
|
||||||
|
@ -14,11 +27,11 @@ import (
|
||||||
// Returns a map of docker clients by server name and an error if any.
|
// Returns a map of docker clients by server name and an error if any.
|
||||||
//
|
//
|
||||||
// Even if there are errors, the map of docker clients might not be empty.
|
// Even if there are errors, the map of docker clients might not be empty.
|
||||||
func getDockerClients() (map[string]*docker.SharedClient, gperr.Error) {
|
func getDockerClients() (DockerClients, gperr.Error) {
|
||||||
cfg := config.GetInstance()
|
cfg := config.GetInstance()
|
||||||
|
|
||||||
dockerHosts := cfg.Value().Providers.Docker
|
dockerHosts := cfg.Value().Providers.Docker
|
||||||
dockerClients := make(map[string]*docker.SharedClient)
|
dockerClients := make(DockerClients)
|
||||||
|
|
||||||
connErrs := gperr.NewBuilder("failed to connect to docker")
|
connErrs := gperr.NewBuilder("failed to connect to docker")
|
||||||
|
|
||||||
|
@ -43,21 +56,6 @@ func getDockerClients() (map[string]*docker.SharedClient, gperr.Error) {
|
||||||
return dockerClients, connErrs.Error()
|
return dockerClients, connErrs.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
// getDockerClientsWithErrHandling returns a map of docker clients for the current config.
|
|
||||||
//
|
|
||||||
// Returns a map of docker clients by server name and a boolean indicating if http handler should stop/
|
|
||||||
func getDockerClientsWithErrHandling(w http.ResponseWriter) (map[string]*docker.SharedClient, bool) {
|
|
||||||
dockerClients, err := getDockerClients()
|
|
||||||
if err != nil {
|
|
||||||
gperr.LogError("failed to get docker clients", err)
|
|
||||||
if len(dockerClients) == 0 {
|
|
||||||
http.Error(w, "no docker hosts connected successfully", http.StatusInternalServerError)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dockerClients, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDockerClient(w http.ResponseWriter, server string) (*docker.SharedClient, bool, error) {
|
func getDockerClient(w http.ResponseWriter, server string) (*docker.SharedClient, bool, error) {
|
||||||
cfg := config.GetInstance()
|
cfg := config.GetInstance()
|
||||||
var host string
|
var host string
|
||||||
|
@ -86,13 +84,13 @@ func getDockerClient(w http.ResponseWriter, server string) (*docker.SharedClient
|
||||||
// closeAllClients closes all docker clients after a delay.
|
// closeAllClients closes all docker clients after a delay.
|
||||||
//
|
//
|
||||||
// This is used to ensure that all docker clients are closed after the http handler returns.
|
// This is used to ensure that all docker clients are closed after the http handler returns.
|
||||||
func closeAllClients(dockerClients map[string]*docker.SharedClient) {
|
func closeAllClients(dockerClients DockerClients) {
|
||||||
for _, dockerClient := range dockerClients {
|
for _, dockerClient := range dockerClients {
|
||||||
dockerClient.Close()
|
dockerClient.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleResult[T any](w http.ResponseWriter, errs error, result []T) {
|
func handleResult[V any, T ResultType[V]](w http.ResponseWriter, errs error, result T) {
|
||||||
if errs != nil {
|
if errs != nil {
|
||||||
gperr.LogError("docker errors", errs)
|
gperr.LogError("docker errors", errs)
|
||||||
if len(result) == 0 {
|
if len(result) == 0 {
|
||||||
|
@ -102,3 +100,25 @@ func handleResult[T any](w http.ResponseWriter, errs error, result []T) {
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(result)
|
json.NewEncoder(w).Encode(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serveHTTP[V any, T ResultType[V]](w http.ResponseWriter, r *http.Request, getResult func(ctx context.Context, dockerClients DockerClients) (T, gperr.Error)) {
|
||||||
|
dockerClients, err := getDockerClients()
|
||||||
|
if err != nil {
|
||||||
|
handleResult[V, T](w, err, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer closeAllClients(dockerClients)
|
||||||
|
|
||||||
|
if httpheaders.IsWebsocket(r.Header) {
|
||||||
|
gpwebsocket.Periodic(w, r, 5*time.Second, func(conn *websocket.Conn) error {
|
||||||
|
result, err := getResult(r.Context(), dockerClients)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return wsjson.Write(r.Context(), conn, result)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
result, err := getResult(r.Context(), dockerClients)
|
||||||
|
handleResult[V, T](w, err, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue