I am not proud of it.
Why did I choose to do this. I could get some more sleep but I choose to write this. I just want some snapshot before I start breaking stuff.
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ssh-key
|
||||||
|
ssh-key.pub
|
||||||
15
config.json
Normal file
15
config.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"Nodes": {
|
||||||
|
"rpi":{
|
||||||
|
"Ip": "192.168.1.175",
|
||||||
|
"DockerVolumePath": "/var/lib/docker/volumes"
|
||||||
|
},
|
||||||
|
"arnost":{
|
||||||
|
"Ip": "192.168.1.9",
|
||||||
|
"DockerVolumePath": "/home/blazena/volumes"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DockerManagerBaseUrl": "http://localhost:1234",
|
||||||
|
"User": "blazena",
|
||||||
|
"LocalBasePath": "/archive/@backups"
|
||||||
|
}
|
||||||
11
config/config.go
Normal file
11
config/config.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package config;
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Nodes map[string] struct{
|
||||||
|
Ip string
|
||||||
|
DockerVolumePath string
|
||||||
|
}
|
||||||
|
DockerManagerBaseUrl string
|
||||||
|
User string
|
||||||
|
LocalBasePath string
|
||||||
|
};
|
||||||
128
docker/docker.go
Normal file
128
docker/docker.go
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/moby/moby/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add mutex.
|
||||||
|
var ApiClient *client.Client;
|
||||||
|
var scale sync.Map;
|
||||||
|
var token string = "12345";
|
||||||
|
|
||||||
|
type aService struct{
|
||||||
|
ServiceId string `json:"serviceId"`;
|
||||||
|
VolumeNames []string `json:"volumeNames"`;
|
||||||
|
Node string `json:"node"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
func Run(){
|
||||||
|
ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM);
|
||||||
|
|
||||||
|
var err error;
|
||||||
|
ApiClient, err = client.New(client.FromEnv);
|
||||||
|
if(err != nil){
|
||||||
|
panic("Docker client was not able to init from env!" + err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := ApiClient.Info(context.Background(), client.InfoOptions{});
|
||||||
|
if(err != nil){
|
||||||
|
panic("Error getting info!" + err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!info.Info.Swarm.ControlAvailable){
|
||||||
|
panic("Node is not a swarm manager.");
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &http.Server{
|
||||||
|
Addr: ":1234",
|
||||||
|
}
|
||||||
|
|
||||||
|
http.HandleFunc("/services", listServices);
|
||||||
|
http.HandleFunc("/scale/down", scaleDown);
|
||||||
|
http.HandleFunc("/scale/up", scaleUp);
|
||||||
|
http.HandleFunc("/prepare", prepare);
|
||||||
|
go func(){
|
||||||
|
err = server.ListenAndServe();
|
||||||
|
if err == http.ErrServerClosed {
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(err != nil){
|
||||||
|
panic("Unable to start http server!" + err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
}();
|
||||||
|
|
||||||
|
time.Sleep(10*time.Millisecond);
|
||||||
|
<-ctx.Done();
|
||||||
|
fmt.Println("Stopping http server.");
|
||||||
|
server.Close();
|
||||||
|
fmt.Println("Exiting!");
|
||||||
|
}
|
||||||
|
|
||||||
|
func bearerAuth(w http.ResponseWriter, r *http.Request)bool {
|
||||||
|
authHeader := r.Header.Get("Authorization")
|
||||||
|
expected := "Bearer " + token
|
||||||
|
|
||||||
|
if authHeader != expected {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
fmt.Fprintln(w, "Unauthorized")
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
func listServices(w http.ResponseWriter, r *http.Request){
|
||||||
|
if(r.Method != http.MethodGet){
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bearerAuth(w,r) {return};
|
||||||
|
|
||||||
|
list, err := ApiClient.ServiceList(context.Background(), client.ServiceListOptions{});
|
||||||
|
if(err != nil){
|
||||||
|
panic("Unable to list services!" + err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
var services []aService;
|
||||||
|
|
||||||
|
for _, service:= range list.Items{
|
||||||
|
var settings map[string]string = service.Spec.Labels;
|
||||||
|
|
||||||
|
|
||||||
|
if(settings["blazena.enable"] != "true"){
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
targetVolumes := strings.Split(settings["blazena.volumes"], ",");
|
||||||
|
|
||||||
|
services = append(services, aService{
|
||||||
|
ServiceId: service.ID,
|
||||||
|
VolumeNames: targetVolumes,
|
||||||
|
Node: settings["blazena.node"],
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(services);
|
||||||
|
|
||||||
|
if err != nil{
|
||||||
|
panic("Error during response encoding!" + err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(w, string(bytes));
|
||||||
|
}
|
||||||
69
docker/prepare.go
Normal file
69
docker/prepare.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/moby/moby/api/types/swarm"
|
||||||
|
"github.com/moby/moby/api/types/mount"
|
||||||
|
"github.com/moby/moby/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func prepare(w http.ResponseWriter, r *http.Request){
|
||||||
|
if r.Method != http.MethodPost{
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed);
|
||||||
|
fmt.Fprint(w, "Method Not Allowed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: add token auth
|
||||||
|
|
||||||
|
rawBody, err := io.ReadAll(r.Body);
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to read body!");
|
||||||
|
}
|
||||||
|
|
||||||
|
var bodyDecoded struct{
|
||||||
|
volume string
|
||||||
|
node string
|
||||||
|
};
|
||||||
|
|
||||||
|
err = json.Unmarshal(rawBody, &bodyDecoded);
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to unmarshal json."+ err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
maxConcurrent := uint64(1);
|
||||||
|
totalCompletions := uint64(1);
|
||||||
|
targetVolume := bodyDecoded.volume;
|
||||||
|
targetNode := bodyDecoded.node;
|
||||||
|
|
||||||
|
ApiClient.ServiceCreate(context.Background(), client.ServiceCreateOptions{
|
||||||
|
Spec: swarm.ServiceSpec{
|
||||||
|
Mode: swarm.ServiceMode{
|
||||||
|
ReplicatedJob: &swarm.ReplicatedJob{
|
||||||
|
MaxConcurrent: &maxConcurrent,
|
||||||
|
TotalCompletions: &totalCompletions,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TaskTemplate: swarm.TaskSpec{
|
||||||
|
ContainerSpec: &swarm.ContainerSpec{
|
||||||
|
Image: "docker.io/library/alpine:latest",
|
||||||
|
Mounts: []mount.Mount{
|
||||||
|
mount.Mount{
|
||||||
|
Source: targetVolume,
|
||||||
|
Target: "/volume",
|
||||||
|
Type: "bind",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Placement: &swarm.Placement{
|
||||||
|
Constraints: []string{"node.hostname=="+targetNode},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
105
docker/scale.go
Normal file
105
docker/scale.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package docker;
|
||||||
|
import(
|
||||||
|
"net/http"
|
||||||
|
"io"
|
||||||
|
"encoding/json"
|
||||||
|
"context"
|
||||||
|
"github.com/moby/moby/client"
|
||||||
|
);
|
||||||
|
|
||||||
|
func scaleDown(w http.ResponseWriter, r *http.Request){
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bearerAuth(w, r) {return}
|
||||||
|
|
||||||
|
rawBody, err := io.ReadAll(r.Body);
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to read body!" + err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedBody struct{
|
||||||
|
ServiceId string `json:"serviceId"`;
|
||||||
|
};
|
||||||
|
|
||||||
|
err = json.Unmarshal(rawBody, &parsedBody);
|
||||||
|
if err != nil{
|
||||||
|
panic("Failed to unmarshal request body!"+ err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
inspectresoult, err := ApiClient.ServiceInspect(context.Background(), parsedBody.ServiceId, client.ServiceInspectOptions{});
|
||||||
|
|
||||||
|
if err != nil{
|
||||||
|
panic("Error inspecting service!"+ err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
originalScale := inspectresoult.Service.Spec.Mode.Replicated.Replicas;
|
||||||
|
updatedSpec := inspectresoult.Service.Spec;
|
||||||
|
|
||||||
|
newScale := uint64(0);
|
||||||
|
updatedSpec.Mode.Replicated.Replicas = &newScale;
|
||||||
|
|
||||||
|
scale.Store(parsedBody.ServiceId, *originalScale);
|
||||||
|
|
||||||
|
_, err = ApiClient.ServiceUpdate(context.Background(), parsedBody.ServiceId, client.ServiceUpdateOptions{
|
||||||
|
Spec: updatedSpec,
|
||||||
|
Version: inspectresoult.Service.Version,
|
||||||
|
});
|
||||||
|
|
||||||
|
if(err != nil){
|
||||||
|
panic("Failed to update service."+ err.Error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func scaleUp(w http.ResponseWriter, r *http.Request){
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bearerAuth(w, r) {return}
|
||||||
|
|
||||||
|
|
||||||
|
rawBody, err := io.ReadAll(r.Body);
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to read body!");
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedBody struct{
|
||||||
|
ServiceId string `json:"serviceId"`;
|
||||||
|
};
|
||||||
|
|
||||||
|
err = json.Unmarshal(rawBody, &parsedBody);
|
||||||
|
if err != nil{
|
||||||
|
panic("Failed to unmarshal request body!"+ err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
inspectresoult, err := ApiClient.ServiceInspect(context.Background(), parsedBody.ServiceId, client.ServiceInspectOptions{});
|
||||||
|
|
||||||
|
if err != nil{
|
||||||
|
panic("Error inspecting service!"+ err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
originalScale, ok := scale.Load(parsedBody.ServiceId);
|
||||||
|
if(!ok){
|
||||||
|
panic("Its not okay!");
|
||||||
|
}
|
||||||
|
|
||||||
|
originalScaleChecked, ok := originalScale.(uint64);
|
||||||
|
if(!ok){
|
||||||
|
panic("Its very not okay!")
|
||||||
|
}
|
||||||
|
updatedSpec := inspectresoult.Service.Spec;
|
||||||
|
|
||||||
|
updatedSpec.Mode.Replicated.Replicas = &originalScaleChecked;
|
||||||
|
|
||||||
|
|
||||||
|
ApiClient.ServiceUpdate(context.Background(), parsedBody.ServiceId, client.ServiceUpdateOptions{
|
||||||
|
Spec: updatedSpec,
|
||||||
|
Version: inspectresoult.Service.Version,
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
26
go.mod
Normal file
26
go.mod
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
module github.com/rony5394/blazena
|
||||||
|
|
||||||
|
go 1.25.5
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
|
github.com/containerd/errdefs v1.0.0 // indirect
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||||
|
github.com/distribution/reference v0.6.0 // indirect
|
||||||
|
github.com/docker/go-connections v0.6.0 // indirect
|
||||||
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
|
github.com/moby/moby/api v1.52.0 // indirect
|
||||||
|
github.com/moby/moby/client v0.2.1 // indirect
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
|
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||||
|
golang.org/x/sys v0.33.0 // indirect
|
||||||
|
)
|
||||||
41
go.sum
Normal file
41
go.sum
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
|
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||||
|
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||||
|
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/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||||
|
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
||||||
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
|
github.com/moby/moby/api v1.52.0 h1:00BtlJY4MXkkt84WhUZPRqt5TvPbgig2FZvTbe3igYg=
|
||||||
|
github.com/moby/moby/api v1.52.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc=
|
||||||
|
github.com/moby/moby/client v0.2.1 h1:1Grh1552mvv6i+sYOdY+xKKVTvzJegcVMhuXocyDz/k=
|
||||||
|
github.com/moby/moby/client v0.2.1/go.mod h1:O+/tw5d4a1Ha/ZA/tPxIZJapJRUS6LNZ1wiVRxYHyUE=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
|
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||||
|
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
|
||||||
|
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||||
|
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||||
|
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||||
|
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||||
|
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||||
|
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||||
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
63
host/host.go
Normal file
63
host/host.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package host
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
cfg "github.com/rony5394/blazena/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var token string = "12345";
|
||||||
|
|
||||||
|
type aService struct{
|
||||||
|
ServiceId string `json:"serviceId"`;
|
||||||
|
VolumeNames []string `json:"volumeNames"`;
|
||||||
|
Node string `json:"node"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
func Run(Config cfg.Config) {
|
||||||
|
services := getServices(Config);
|
||||||
|
|
||||||
|
for _, service := range services {
|
||||||
|
_, ok := Config.Nodes[service.Node];
|
||||||
|
if !ok {
|
||||||
|
fmt.Println("Node", service.Node, "refferenced in", service.ServiceId ,"service does not exists!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for _, volume := range service.VolumeNames{
|
||||||
|
remoteFilePath := Config.Nodes[service.Node].DockerVolumePath + "/" + volume;
|
||||||
|
remotePath := Config.User + "@" + Config.Nodes[service.Node].Ip + ":" + remoteFilePath;
|
||||||
|
base := "rsync -avh --delete --progress -e 'ssh -i ./ssh-key' ";
|
||||||
|
localPath := Config.LocalBasePath + "/@current/@" + service.Node;
|
||||||
|
|
||||||
|
fmt.Println(base + remotePath + " " + localPath);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getServices(Config cfg.Config)[]aService{
|
||||||
|
req, err := http.NewRequest("GET", Config.DockerManagerBaseUrl + "/services", nil);
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to create request."+ err.Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Add("Authorization", "Bearer "+ token);
|
||||||
|
|
||||||
|
res, err := http.DefaultClient.Do(req);
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to send request."+ err.Error());
|
||||||
|
}
|
||||||
|
reader, err := io.ReadAll(res.Body);
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to decode response body."+err.Error());
|
||||||
|
}
|
||||||
|
var services []aService;
|
||||||
|
err = json.Unmarshal(reader, &services);
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to unmarshal response.");
|
||||||
|
}
|
||||||
|
return services;
|
||||||
|
}
|
||||||
44
main.go
Normal file
44
main.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
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 <mode>");
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
|
||||||
|
mode := os.Args[1];
|
||||||
|
switch mode {
|
||||||
|
case "docker":
|
||||||
|
docker.Run();
|
||||||
|
break;
|
||||||
|
case "host":
|
||||||
|
host.Run(Config);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
panic("Invalid runtime mode!");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user