mirror of
https://github.com/zix99/traefik-lazyload.git
synced 2025-12-21 21:33:09 +01:00
Configurable waitforcode
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# traefik-lazyloader
|
# traefik-lazyloader
|
||||||
|
|
||||||
Takes advantage of traefik's router priority to hit this small application that will manage
|
Takes advantage of traefik's router priority to proxy to this small application that will manage
|
||||||
starting/stopping containers to save resources.
|
starting/stopping containers to save resources.
|
||||||
|
|
||||||
## Quick-Start
|
## Quick-Start
|
||||||
@@ -9,8 +9,10 @@ starting/stopping containers to save resources.
|
|||||||
|
|
||||||
## Labels
|
## Labels
|
||||||
|
|
||||||
* `lazyloader=true` -- Add to containers that should be managed
|
* `lazyloader=true` -- (Required) Add to containers that should be managed
|
||||||
* `lazyloader.stopdelay=5m` -- Amount of time to wait for idle network traffick before stopping a container (default: 5m)
|
* `lazyloader.stopdelay=5m` -- Amount of time to wait for idle network traffick before stopping a container
|
||||||
|
* `lazyloader.waitforcode=200` -- Waits for this HTTP result from downstream before redirecting user
|
||||||
|
* `lazyloader.waitforpath=/` -- Checks this path downstream to check for the process being ready, using the `waitforcode`
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@
|
|||||||
return response.status === {{.WaitForCode}};
|
return response.status === {{.WaitForCode}};
|
||||||
}
|
}
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
console.log("testing...");
|
|
||||||
if (await testForOk("{{.WaitForPath}}")) {
|
if (await testForOk("{{.WaitForPath}}")) {
|
||||||
console.log("Found! Reloading...")
|
console.log("Found! Reloading...")
|
||||||
location.reload();
|
location.reload();
|
||||||
|
|||||||
51
main.go
51
main.go
@@ -11,6 +11,7 @@ import (
|
|||||||
"io/fs"
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -37,10 +38,12 @@ var splashTemplate = template.Must(template.ParseFS(httpAssets, "assets/splash.h
|
|||||||
var dockerClient *client.Client
|
var dockerClient *client.Client
|
||||||
|
|
||||||
type containerState struct {
|
type containerState struct {
|
||||||
Name, ID string
|
Name, ID string
|
||||||
IsRunning bool
|
IsRunning bool
|
||||||
LastWork time.Time
|
LastWork time.Time
|
||||||
StopDelay time.Duration
|
StopDelay time.Duration
|
||||||
|
WaitForCode int
|
||||||
|
WaitForPath string
|
||||||
|
|
||||||
lastRecv, lastSend int64 // Last network traffic, used to see if idle
|
lastRecv, lastSend int64 // Last network traffic, used to see if idle
|
||||||
}
|
}
|
||||||
@@ -167,17 +170,6 @@ func ContainerHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
ct, _ := findContainerByHostname(r.Context(), host)
|
ct, _ := findContainerByHostname(r.Context(), host)
|
||||||
if ct != nil || true {
|
if ct != nil || true {
|
||||||
// TODO: Send response before querying anything about the container (the slow bit)
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
renderErr := splashTemplate.Execute(w, SplashModel{
|
|
||||||
Name: host,
|
|
||||||
WaitForCode: 200, // TODO Config-based
|
|
||||||
WaitForPath: "/",
|
|
||||||
})
|
|
||||||
if renderErr != nil {
|
|
||||||
logrus.Error(renderErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look to start the container
|
// Look to start the container
|
||||||
state := getOrCreateState(ct.ID)
|
state := getOrCreateState(ct.ID)
|
||||||
logrus.Infof("Found container %s for host %s, checking state...", containerShort(ct), host)
|
logrus.Infof("Found container %s for host %s, checking state...", containerShort(ct), host)
|
||||||
@@ -194,6 +186,16 @@ func ContainerHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
state.LastWork = time.Now()
|
state.LastWork = time.Now()
|
||||||
parseContainerSettings(state, ct)
|
parseContainerSettings(state, ct)
|
||||||
} // TODO: What if container crahsed but we think it's started?
|
} // TODO: What if container crahsed but we think it's started?
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
renderErr := splashTemplate.Execute(w, SplashModel{
|
||||||
|
Name: host,
|
||||||
|
WaitForCode: state.WaitForCode,
|
||||||
|
WaitForPath: state.WaitForPath,
|
||||||
|
})
|
||||||
|
if renderErr != nil {
|
||||||
|
logrus.Error(renderErr)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logrus.Warnf("Unable to find container for host %s", host)
|
logrus.Warnf("Unable to find container for host %s", host)
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
@@ -212,14 +214,25 @@ func getOrCreateState(cid string) (ret *containerState) {
|
|||||||
|
|
||||||
func parseContainerSettings(target *containerState, ct *types.Container) {
|
func parseContainerSettings(target *containerState, ct *types.Container) {
|
||||||
{ // Parse stop delay
|
{ // Parse stop delay
|
||||||
var stopErr error
|
|
||||||
stopDelay, _ := labelOrDefault(ct, "stopdelay", "10s")
|
stopDelay, _ := labelOrDefault(ct, "stopdelay", "10s")
|
||||||
target.StopDelay, stopErr = time.ParseDuration(stopDelay)
|
if dur, stopErr := time.ParseDuration(stopDelay); stopErr != nil {
|
||||||
if stopErr != nil {
|
target.StopDelay = 30 * time.Second // TODO: Use config for default
|
||||||
target.StopDelay = 30 * time.Second
|
|
||||||
logrus.Warnf("Unable to parse stopdelay of %s, defaulting to %s", stopDelay, target.StopDelay.String())
|
logrus.Warnf("Unable to parse stopdelay of %s, defaulting to %s", stopDelay, target.StopDelay.String())
|
||||||
|
} else {
|
||||||
|
target.StopDelay = dur
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{ // WaitForCode
|
||||||
|
codeStr, _ := labelOrDefault(ct, "waitforcode", "200")
|
||||||
|
if code, err := strconv.Atoi(codeStr); err != nil {
|
||||||
|
target.WaitForCode = 200
|
||||||
|
logrus.Warnf("Unable to parse WaitForCode of %s, defaulting to %d", target.Name, target.WaitForCode)
|
||||||
|
} else {
|
||||||
|
target.WaitForCode = code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target.WaitForPath, _ = labelOrDefault(ct, "waitforpath", "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func findContainerByHostname(ctx context.Context, hostname string) (*types.Container, error) {
|
func findContainerByHostname(ctx context.Context, hostname string) (*types.Container, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user