From ec797025e5677781b4f66f382deb9bae8c576810 Mon Sep 17 00:00:00 2001 From: rony5394 <143897221+rony5394@users.noreply.github.com> Date: Sun, 22 Mar 2026 21:16:58 +0100 Subject: [PATCH] Some Refactoring. --- config/config.go | 34 ++++++- docker/docker.go | 4 +- docker/prepare.go | 10 +- host/createHost.go | 94 +++++++++++++++++++ host/exchangeKeys.go | 59 ++++++++++++ host/host.go | 211 +------------------------------------------ host/prepare.go | 50 ++++++++++ host/scale.go | 49 ++++++++++ main.go | 22 +---- 9 files changed, 299 insertions(+), 234 deletions(-) create mode 100644 host/createHost.go create mode 100644 host/exchangeKeys.go create mode 100644 host/prepare.go create mode 100644 host/scale.go diff --git a/config/config.go b/config/config.go index 7ac9026..eee570e 100644 --- a/config/config.go +++ b/config/config.go @@ -1,5 +1,10 @@ package config; +import ( + "os" + "encoding/json" +); + type Config struct { Nodes map[string] struct{ Ip string @@ -9,9 +14,36 @@ type Config struct { LocalBasePath string BlazenaImageUrl string RegistryAuth RegistryAuth -}; + Constants struct{ + OverlayNetworkName string + HelperServiceName string + StorageContainerName string + } +} type RegistryAuth struct { Username string Password string } + +func GetConfig() Config { + var cfg Config; + + rawConfig, err := os.ReadFile("./config.json"); + if err != nil{ + panic("Failed it load config file." + err.Error()); + } + + cfg.Constants.OverlayNetworkName = "blazenaPohar"; + cfg.Constants.HelperServiceName = "blazenaHelper"; + cfg.Constants.StorageContainerName = "blazenaStorage"; + + + err = json.Unmarshal(rawConfig, &cfg); + + if err != nil{ + panic("Failed to unmarshal config." + err.Error()) + } + + return cfg; +} diff --git a/docker/docker.go b/docker/docker.go index 2929551..bce1867 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -68,7 +68,7 @@ func Run(Config cfg.Config){ stop(); }); - ApiClient.NetworkCreate(context.Background(), "blazenaPohar", network.CreateOptions{ + ApiClient.NetworkCreate(context.Background(), theConfig.Constants.OverlayNetworkName, network.CreateOptions{ Attachable: true, // Internal: true, Driver: "overlay", @@ -96,7 +96,7 @@ func Run(Config cfg.Config){ fmt.Println("Stopping http server."); server.Close(); - ApiClient.NetworkRemove(context.Background(), "blazenaPohar"); + ApiClient.NetworkRemove(context.Background(), theConfig.Constants.OverlayNetworkName); ApiClient.ConfigRemove(context.Background(), "blazenaSSHPublicKey") ApiClient.SecretRemove(context.Background(), "blazenaSSHHostPrivateKey"); diff --git a/docker/prepare.go b/docker/prepare.go index 9bdb6d6..07137aa 100644 --- a/docker/prepare.go +++ b/docker/prepare.go @@ -14,6 +14,8 @@ import ( "github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/image" "github.com/docker/docker/client" + + cfg "github.com/rony5394/blazena/config" ) func prepare(w http.ResponseWriter, r *http.Request){ @@ -49,7 +51,7 @@ func prepare(w http.ResponseWriter, r *http.Request){ labels := inspectResoults.Spec.Labels; pullBlazenaImage(); - createHelper(labels["blazena.node"], bodyDecoded.VolumeId); + createHelper(theConfig, labels["blazena.node"], bodyDecoded.VolumeId); time.Sleep(7*time.Second); @@ -121,7 +123,7 @@ func pullBlazenaImage(){ io.Copy(io.Discard, ipc); } -func createHelper(targetNode string, targetVolume string){ +func createHelper(Config cfg.Config, targetNode string, targetVolume string){ maxConcurrent := uint64(1); totalCompletions := uint64(1); stopGracePeriod := time.Second * 5; @@ -136,7 +138,7 @@ func createHelper(targetNode string, targetVolume string){ sshHostKeySecretId, err := getSecretIDByName(ApiClient, "blazenaSSHHostPrivateKey") _, err = ApiClient.ServiceCreate(context.Background(), swarm.ServiceSpec{ Annotations: swarm.Annotations{ - Name: "BlazenaHelper", + Name: Config.Constants.HelperServiceName, Labels: map[string]string{"blazena.helper": "true"}, }, Mode: swarm.ServiceMode{ @@ -187,7 +189,7 @@ func createHelper(targetNode string, targetVolume string){ Constraints: []string{"node.hostname=="+targetNode}, }, Networks: []swarm.NetworkAttachmentConfig{swarm.NetworkAttachmentConfig{ - Target: "blazenaPohar", + Target: Config.Constants.OverlayNetworkName, }}, }, }, swarm.ServiceCreateOptions{}); diff --git a/host/createHost.go b/host/createHost.go new file mode 100644 index 0000000..ebefc1f --- /dev/null +++ b/host/createHost.go @@ -0,0 +1,94 @@ +package host + +import ( + cfg "github.com/rony5394/blazena/config" + "github.com/docker/docker/client" + "encoding/json" + "encoding/base64" + "context" + "io" + "os" + "archive/tar" + "bytes" + "github.com/docker/docker/api/types/image" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/mount" + "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/api/types/strslice" + v1 "github.com/opencontainers/image-spec/specs-go/v1" +); + +func createStorageContainer(Config cfg.Config, DockerClient *client.Client, sshSkPem string, sshHostPkPem string){ + authConfig := registry.AuthConfig{ + Username: Config.RegistryAuth.Username, + Password: Config.RegistryAuth.Password, + } + + authJSON, err := json.Marshal(authConfig) + if err != nil { + panic("Failed to marshal auth config!"+ err.Error()); + } + + authString := base64.URLEncoding.EncodeToString(authJSON); + + ipc, err := DockerClient.ImagePull(context.Background(), Config.BlazenaImageUrl, image.PullOptions{RegistryAuth: authString}); + if err != nil { + panic("Failed to pull blazena image!"+ err.Error()); + } + defer ipc.Close(); + + io.Copy(io.Discard, ipc); + + cr, err := DockerClient.ContainerCreate(context.Background(), &container.Config{ + Image: Config.BlazenaImageUrl, + Labels: map[string]string{ + "blazena.storage": "true", + }, + Cmd: strslice.StrSlice{"sleep", "3h"}, + }, &container.HostConfig{ + Mounts: []mount.Mount{ + mount.Mount{ + Type: mount.TypeBind, + Source: Config.LocalBasePath, + Target: "/volume", + ReadOnly: true, + }, + }, + //AutoRemove: true, + NetworkMode: container.NetworkMode(Config.Constants.OverlayNetworkName), + }, &network.NetworkingConfig{ + }, &v1.Platform{}, Config.Constants.StorageContainerName); + + if err != nil { + panic("Failed to create BlazenaStorage container!"+err.Error()); + } + + err = DockerClient.ContainerStart(context.Background(), cr.ID, container.StartOptions{}); + + if err != nil{ + panic("Failed to start BlazenaStorage container!"+err.Error()); + } + + + var buf bytes.Buffer; + tw := tar.NewWriter(&buf); + + addToTar(tw, "ssh-key", sshSkPem); + addToTar(tw, "expected-host-key", "[tasks."+ Config.Constants.HelperServiceName +"]:2222 "+ sshHostPkPem); + tw.Close(); + if err != nil {panic("The british are comming!")} + + os.WriteFile("/tmp/test", buf.Bytes(), os.ModeAppend); + + err = DockerClient.CopyToContainer(context.Background(), Config.Constants.StorageContainerName, "/", &buf, container.CopyToContainerOptions{ + AllowOverwriteDirWithFile: true, + }); + if err != nil { + panic("Failed to copy ssh key to container!"+err.Error()); + } + + +} + + diff --git a/host/exchangeKeys.go b/host/exchangeKeys.go new file mode 100644 index 0000000..bc3c5da --- /dev/null +++ b/host/exchangeKeys.go @@ -0,0 +1,59 @@ +package host + +import ( + "encoding/json" + "io" + "net/http" + "bytes" + cfg "github.com/rony5394/blazena/config" +); + +func exchangeKeys(Config cfg.Config, sshKeyPem string)string{ + var body struct{ + SshPkPem string `json:"sshPkPem"` + } = struct{SshPkPem string `json:"sshPkPem"`}{ + SshPkPem: sshKeyPem, + }; + + bodyEncoded, err := json.Marshal(body); + + if err != nil { + panic("Failed to marshal body."+ err.Error()); + } + + rq, err := http.NewRequest("POST", Config.DockerManagerBaseUrl + "/keys", 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); + + if err != nil{ + panic("Failed to send http request"+ err.Error()); + } + + defer rs.Body.Close(); + + rsBodyRaw, err := io.ReadAll(rs.Body); + + if err != nil{ + panic("Failed to read response's body!"+err.Error()); + } + + var rsBody struct{ + HostPkPem string `json:"hostPkPem"` + }; + + err = json.Unmarshal(rsBodyRaw, &rsBody); + if err != nil{ + panic("Failed to unmarshal rsBodyRaw!"+ err.Error()); + } + + + return rsBody.HostPkPem; +} + + diff --git a/host/host.go b/host/host.go index 525cbb0..ccf303b 100644 --- a/host/host.go +++ b/host/host.go @@ -4,7 +4,6 @@ import ( "archive/tar" "bytes" "context" - "encoding/base64" "encoding/json" "fmt" "io" @@ -13,13 +12,7 @@ import ( "time" "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/api/types/strslice" "github.com/docker/docker/client" - v1 "github.com/opencontainers/image-spec/specs-go/v1" cfg "github.com/rony5394/blazena/config" "github.com/rony5394/blazena/shared" ) @@ -60,9 +53,9 @@ func Run(Config cfg.Config) { // Skiping Host Key Check is temporary. command := `rsync -avz --delete -e "ssh -i /ssh-key -p 2222 -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/expected-host-key" \ - root@tasks.BlazenaHelper:/volume/ /tmp/` + volume; + root@tasks.`+ Config.Constants.HelperServiceName +`:/volume/ /tmp/` + volume; - exec, err := DockerClient.ContainerExecCreate(context.Background(), "BlazenaStorage", container.ExecOptions{ + exec, err := DockerClient.ContainerExecCreate(context.Background(), Config.Constants.StorageContainerName, container.ExecOptions{ Cmd: []string{"sh", "-c", command}, AttachStdout: true, AttachStderr: true, @@ -88,7 +81,7 @@ func Run(Config cfg.Config) { fmt.Println("Done!"); } - DockerClient.ContainerRemove(context.Background(), "BlazenaStorage", container.RemoveOptions{ + DockerClient.ContainerRemove(context.Background(), Config.Constants.StorageContainerName, container.RemoveOptions{ Force: true, }); @@ -119,45 +112,6 @@ func getServices(Config cfg.Config)[]aService{ return services; } -func prepareService(Config cfg.Config, service aService, targetVolume string) bool{ - _, ok := Config.Nodes[service.Node]; - if !ok { - fmt.Println("Node", service.Node, "refferenced in", service.ServiceId ,"service does not exists!"); - return false; - } - - var body struct{ - ServiceId string `json:"serviceId"` - VolumeId string `json:"volumeId"` - } = struct{ServiceId string "json:\"serviceId\""; VolumeId string "json:\"volumeId\""}{ - ServiceId: service.ServiceId, - VolumeId: targetVolume, - } - - bodyEncoded, err := json.Marshal(body); - - if err != nil { - panic("Failed to marshal body."+ err.Error()); - } - - rq, err := http.NewRequest("POST", Config.DockerManagerBaseUrl + "/prepare", 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 cleanupService(Config cfg.Config, service aService)bool{ _, ok := Config.Nodes[service.Node]; if !ok { @@ -197,117 +151,6 @@ 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, sshSkPem string, sshHostPkPem string){ - authConfig := registry.AuthConfig{ - Username: Config.RegistryAuth.Username, - Password: Config.RegistryAuth.Password, - } - - authJSON, err := json.Marshal(authConfig) - if err != nil { - panic("Failed to marshal auth config!"+ err.Error()); - } - - authString := base64.URLEncoding.EncodeToString(authJSON); - - ipc, err := DockerClient.ImagePull(context.Background(), Config.BlazenaImageUrl, image.PullOptions{RegistryAuth: authString}); - if err != nil { - panic("Failed to pull blazena image!"+ err.Error()); - } - defer ipc.Close(); - - io.Copy(io.Discard, ipc); - - cr, err := DockerClient.ContainerCreate(context.Background(), &container.Config{ - Image: Config.BlazenaImageUrl, - Labels: map[string]string{ - "blazena.storage": "true", - }, - Cmd: strslice.StrSlice{"sleep", "3h"}, - }, &container.HostConfig{ - Mounts: []mount.Mount{ - mount.Mount{ - Type: mount.TypeBind, - Source: Config.LocalBasePath, - Target: "/volume", - ReadOnly: true, - }, - }, - //AutoRemove: true, - NetworkMode: "blazenaPohar", - }, &network.NetworkingConfig{ - }, &v1.Platform{}, "BlazenaStorage"); - - if err != nil { - panic("Failed to create BlazenaStorage container!"+err.Error()); - } - - err = DockerClient.ContainerStart(context.Background(), cr.ID, container.StartOptions{}); - - if err != nil{ - panic("Failed to start BlazenaStorage container!"+err.Error()); - } - - - var buf bytes.Buffer; - tw := tar.NewWriter(&buf); - - addToTar(tw, "ssh-key", sshSkPem); - addToTar(tw, "expected-host-key", "[tasks.BlazenaHelper]:2222 "+ sshHostPkPem); - tw.Close(); - if err != nil {panic("The british are comming!")} - - os.WriteFile("/tmp/test", buf.Bytes(), os.ModeAppend); - - err = DockerClient.CopyToContainer(context.Background(), "BlazenaStorage", "/", &buf, container.CopyToContainerOptions{ - AllowOverwriteDirWithFile: true, - }); - if err != nil { - panic("Failed to copy ssh key to container!"+err.Error()); - } - - -} - func shutdown(Config cfg.Config)bool{ rq, err := http.NewRequest("POST", Config.DockerManagerBaseUrl + "/shutdown", nil); @@ -327,54 +170,6 @@ func shutdown(Config cfg.Config)bool{ } -func exchangeKeys(Config cfg.Config, sshKeyPem string)string{ - var body struct{ - SshPkPem string `json:"sshPkPem"` - } = struct{SshPkPem string `json:"sshPkPem"`}{ - SshPkPem: sshKeyPem, - }; - - bodyEncoded, err := json.Marshal(body); - - if err != nil { - panic("Failed to marshal body."+ err.Error()); - } - - rq, err := http.NewRequest("POST", Config.DockerManagerBaseUrl + "/keys", 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); - - if err != nil{ - panic("Failed to send http request"+ err.Error()); - } - - defer rs.Body.Close(); - - rsBodyRaw, err := io.ReadAll(rs.Body); - - if err != nil{ - panic("Failed to read response's body!"+err.Error()); - } - - var rsBody struct{ - HostPkPem string `json:"hostPkPem"` - }; - - err = json.Unmarshal(rsBodyRaw, &rsBody); - if err != nil{ - panic("Failed to unmarshal rsBodyRaw!"+ err.Error()); - } - - - return rsBody.HostPkPem; -} - func addToTar(tw *tar.Writer, filename string, content string) error{ hdr := &tar.Header{ Name: filename, diff --git a/host/prepare.go b/host/prepare.go new file mode 100644 index 0000000..02a57ce --- /dev/null +++ b/host/prepare.go @@ -0,0 +1,50 @@ +package host + +import( + "fmt" + "encoding/json" + "bytes" + cfg "github.com/rony5394/blazena/config" + "net/http" +); + +func prepareService(Config cfg.Config, service aService, targetVolume string) bool{ + _, ok := Config.Nodes[service.Node]; + if !ok { + fmt.Println("Node", service.Node, "refferenced in", service.ServiceId ,"service does not exists!"); + return false; + } + + var body struct{ + ServiceId string `json:"serviceId"` + VolumeId string `json:"volumeId"` + } = struct{ServiceId string "json:\"serviceId\""; VolumeId string "json:\"volumeId\""}{ + ServiceId: service.ServiceId, + VolumeId: targetVolume, + } + + bodyEncoded, err := json.Marshal(body); + + if err != nil { + panic("Failed to marshal body."+ err.Error()); + } + + rq, err := http.NewRequest("POST", Config.DockerManagerBaseUrl + "/prepare", 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; +} + + diff --git a/host/scale.go b/host/scale.go new file mode 100644 index 0000000..8c5cd00 --- /dev/null +++ b/host/scale.go @@ -0,0 +1,49 @@ +package host + +import ( + cfg "github.com/rony5394/blazena/config" + "encoding/json" + "net/http" + "bytes" +); + +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; +} + + diff --git a/main.go b/main.go index cf4e8a6..ac69d06 100644 --- a/main.go +++ b/main.go @@ -1,42 +1,26 @@ package main import ( - "encoding/json" "os" - "github.com/rony5394/blazena/docker" "github.com/rony5394/blazena/host" cfg "github.com/rony5394/blazena/config" ); -var Config cfg.Config = cfg.Config{ - Nodes: make(map[string]struct{Ip string; DockerVolumePath string}), -}; - - func main() { if(len(os.Args) < 2){ panic("Usage: blazena "); } - rawConfig, err := os.ReadFile("./config.json"); - if err != nil{ - panic("Failed it load config file." + err.Error()); - } - - err = json.Unmarshal(rawConfig, &Config); - - if err != nil{ - panic("Failed to unmarshal config." + err.Error()) - } + var config = cfg.GetConfig(); mode := os.Args[1]; switch mode { case "docker": - docker.Run(Config); + docker.Run(config); break; case "host": - host.Run(Config); + host.Run(config); break; default: panic("Invalid runtime mode!");