From 0175847e89a731abe44f733438aac9208274d9c6 Mon Sep 17 00:00:00 2001 From: rony5394 <143897221+rony5394@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:23:54 +0100 Subject: [PATCH] Separated Scaling from Preparing --- docker/cleanup.go | 5 +--- docker/docker.go | 2 ++ docker/prepare.go | 6 +--- docker/scale.go | 71 +++++++++++++++++++++++++++++++++++++++++++++-- host/host.go | 47 ++++++++++++++++++++++++++++++- 5 files changed, 119 insertions(+), 12 deletions(-) diff --git a/docker/cleanup.go b/docker/cleanup.go index acce8e9..75ec1ed 100644 --- a/docker/cleanup.go +++ b/docker/cleanup.go @@ -57,10 +57,7 @@ func cleanup(w http.ResponseWriter, r *http.Request){ if err != nil { panic("Failed to remove helper service."+ err.Error()); } + time.Sleep(15*time.Second); - //TODO: Add proper wait system - time.Sleep(10*time.Second); - - scaleUp(bodyDecoded.ServiceId); fmt.Fprint(w, bodyDecoded.ServiceId); } diff --git a/docker/docker.go b/docker/docker.go index 703aba3..06e886b 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -52,6 +52,8 @@ func Run(){ } http.HandleFunc("/services", listServices); + http.HandleFunc("/scale/up", scaleUp); + http.HandleFunc("/scale/down", scaleDown); http.HandleFunc("/prepare", prepare); http.HandleFunc("/cleanup", cleanup); diff --git a/docker/prepare.go b/docker/prepare.go index 2060f8e..92b1824 100644 --- a/docker/prepare.go +++ b/docker/prepare.go @@ -36,17 +36,12 @@ func prepare(w http.ResponseWriter, r *http.Request){ panic("Failed to unmarshal json."+ err.Error()); } - scaleDown(bodyDecoded.ServiceId); - //TODO: Add proper wait system - time.Sleep(10*time.Second); - inspectResoults, _, err := ApiClient.ServiceInspectWithRaw(context.Background(), bodyDecoded.ServiceId, swarm.ServiceInspectOptions{}); if err != nil{ panic("Failed to inspect service."+ err.Error()); } labels := inspectResoults.Spec.Labels; - time.Sleep(10); maxConcurrent := uint64(1); totalCompletions := uint64(1); @@ -98,6 +93,7 @@ func prepare(w http.ResponseWriter, r *http.Request){ panic("Failed to create helper service."+ err.Error()); } + time.Sleep(15*time.Second); fmt.Fprint(w, bodyDecoded.ServiceId); } diff --git a/docker/scale.go b/docker/scale.go index 51c4156..d08c3fd 100644 --- a/docker/scale.go +++ b/docker/scale.go @@ -2,17 +2,51 @@ package docker import ( "context" + "io" + "net/http" + "time" + + "encoding/json" + "fmt" "github.com/docker/docker/api/types/swarm" ); -func scaleDown(serviceId string){ +func scaleDown(w http.ResponseWriter, r *http.Request){ + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed); + fmt.Fprint(w, "Method Not Allowed"); + return; + } + + + rawBody, err := io.ReadAll(r.Body); + if err != nil { + panic("Failed to read body!"); + } + + var bodyDecoded struct{ + ServiceId string `json:"serviceId"` + }; + + err = json.Unmarshal(rawBody, &bodyDecoded); + if err != nil { + panic("Failed to unmarshal json."+ err.Error()); + } + + serviceId := bodyDecoded.ServiceId; + inspectresoult, _, err := ApiClient.ServiceInspectWithRaw(context.Background(), serviceId, swarm.ServiceInspectOptions{}); if err != nil{ panic("Error inspecting service!"+ err.Error()); } + if inspectresoult.Spec.Labels["blazena.scaledDown"] != "" { + fmt.Println("Tried to scale down already scaled down service! "+ serviceId); + return; + } + originalScale := inspectresoult.Spec.Mode.Replicated.Replicas; updatedSpec := inspectresoult.Spec; @@ -26,15 +60,45 @@ func scaleDown(serviceId string){ if(err != nil){ panic("Failed to update service."+ err.Error()); } + + //TODO: Add proper wait system + time.Sleep(15 * time.Second); } -func scaleUp(serviceId string){ +func scaleUp(w http.ResponseWriter, r *http.Request){ + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed); + fmt.Fprint(w, "Method Not Allowed"); + return; + } + + + rawBody, err := io.ReadAll(r.Body); + if err != nil { + panic("Failed to read body!"); + } + + var bodyDecoded struct{ + ServiceId string `json:"serviceId"` + }; + + err = json.Unmarshal(rawBody, &bodyDecoded); + if err != nil { + panic("Failed to unmarshal json."+ err.Error()); + } + + serviceId := bodyDecoded.ServiceId; inspectresoult, _, err := ApiClient.ServiceInspectWithRaw(context.Background(), serviceId, swarm.ServiceInspectOptions{}); if err != nil{ panic("Error inspecting service!"+ err.Error()); } + if inspectresoult.Spec.Labels["blazena.scaledDown"] != "true" { + fmt.Println("Tried to scale up service that was not scaled down by blazena! "+serviceId); + return; + } + originalScale, ok := scale.Load(serviceId); if(!ok){ panic("Its not okay!"); @@ -50,4 +114,7 @@ func scaleUp(serviceId string){ delete(updatedSpec.Labels, "blazena.scaledDown"); ApiClient.ServiceUpdate(context.Background(), serviceId, inspectresoult.Version, updatedSpec, swarm.ServiceUpdateOptions{}); + + //TODO: Add proper wait system + time.Sleep(15 * time.Second); } diff --git a/host/host.go b/host/host.go index c0e76a2..cb743df 100644 --- a/host/host.go +++ b/host/host.go @@ -43,6 +43,9 @@ func Run(Config cfg.Config) { services := getServices(Config); for _, service := range services { + fmt.Println("Scaling Down: "+service.ServiceId) + scale(Config, service.ServiceId, false); + fmt.Println("Done!"); for _, volume := range service.VolumeNames{ fmt.Println("Preparing: " + service.ServiceId + " volume: " + volume); if !prepareService(Config, service, volume) {continue} @@ -69,12 +72,15 @@ func Run(Config cfg.Config) { resp, err := DockerClient.ContainerExecAttach(context.Background(), exec.ID, container.ExecStartOptions{}); defer resp.Close(); - io.Copy(os.Stdout, resp.Reader) + //io.Copy(os.Stdout, resp.Reader) fmt.Println("Cleaning Up: " + service.ServiceId); cleanupService(Config, service); fmt.Println("Done!"); } + fmt.Println("Scaling up: "+service.ServiceId); + scale(Config, service.ServiceId, true); + fmt.Println("Done!"); } time.Sleep(15*time.Second); @@ -185,6 +191,45 @@ func cleanupService(Config cfg.Config, service aService)bool{ } +func scale(Config cfg.Config, serviceId string, up bool)bool{ + var body struct{ + ServiceId string `json:"serviceId"` + } = struct{ServiceId string "json:\"serviceId\""}{ + ServiceId: serviceId, + } + + bodyEncoded, err := json.Marshal(body); + + if err != nil { + panic("Failed to marshal body."+ err.Error()); + } + + uri := "/scale"; + + if up { + uri += "/up"; + } else { + uri += "/down"; + } + + rq, err := http.NewRequest("POST", Config.DockerManagerBaseUrl + uri, bytes.NewBuffer(bodyEncoded)); + + if err != nil{ + panic("Failed to create http request"+ err.Error()); + } + + rq.Header.Set("Authorization", "Bearer "+ token); + rq.Close = true; + rs, err := http.DefaultClient.Do(rq); + defer rs.Body.Close(); + + if err != nil{ + panic("Failed to send http request"+ err.Error()); + } + + return true; +} + func createStorageContainer(Config cfg.Config, DockerClient *client.Client){ cr, err := DockerClient.ContainerCreate(context.Background(), &container.Config{ Image: "docker.io/library/alpine:3.3",