9 Commits

Author SHA1 Message Date
cd45bcf5c5 remove comment 2026-05-15 01:25:24 -04:00
8423cf5f69 working commit 2026-05-15 00:50:34 -04:00
62be5ddda7 test 2026-05-15 00:39:51 -04:00
3a88c8d878 dockerfile: update 2026-05-15 00:39:51 -04:00
25d01298e5 println -> log 2026-05-15 00:39:51 -04:00
fd53e28143 api: fix routes 2026-05-15 00:39:51 -04:00
c5e773a694 gofmt 2026-05-15 00:39:51 -04:00
cd47863622 update docker 2026-05-15 00:39:51 -04:00
3775894a5b update docker 2026-05-15 00:39:51 -04:00
7 changed files with 111 additions and 88 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "web"]
path = web
url = ssh://git@git.coopcloud.tech:2222/toolshed/coop-cloud-front.git

View File

@ -1,15 +1,30 @@
FROM golang:1.25
RUN mkdir /backend
COPY . /backend/
RUN go build -C /backend -o app
EXPOSE 3000
COPY --parents ["api", "cli", "internal", "go.mod", "go.sum", "app.go", "/backend/"]
RUN go build -C /backend -o gobackend
FROM node
RUN mkdir /frontend
WORKDIR /frontend
RUN git clone https://git.coopcloud.tech/BornDeleuze/coop-cloud-front
EXPOSE 5173
RUN mkdir /home/node/wizard
COPY --from=0 /backend/gobackend /home/node/wizard/gobackend
COPY --parents web /home/node/wizard
WORKDIR /home/node/wizard/web
RUN npm install .
USER node
RUN curl https://install.abra.coopcloud.tech | bash
ENV ABRA_BIN=/home/node/.local/bin/abra
RUN $ABRA_BIN recipe fetch -a
COPY ./start.sh /
COPY --from=0 /backend/app /backend/app
ENTRYPOINT [ "/start.sh" ]
COPY dot_abra /home/node/.abra/
COPY ssh_config /home/node/.ssh/config
COPY id_ed25519_* /home/node/.ssh/
USER root
RUN chown -R node /home/node/
USER node
EXPOSE 5173 3000
# ENV VITE_API_URL=http://localhost:3000/api
CMD [ "/start.sh" ]

View File

@ -2,7 +2,6 @@
A Go service that exposes RESTful API endpoints to manage Abra programmatically.
Integrates with https://git.coopcloud.tech/BornDeleuze/coop-cloud-front.
## Getting started
- Edit the front-end application to turn off mock mode in `src/routes/Authenticated/App.tsx` and `src/routes/Authenticated/Apps.tsx`.
@ -12,4 +11,4 @@ Integrates with https://git.coopcloud.tech/BornDeleuze/coop-cloud-front.
> [!WARNING]
> This is an extremely early prototype, only viewing apps is supported
> and may fail for your local machine
> and may fail for your local machine

View File

@ -1,9 +1,11 @@
package api
import (
"context"
"encoding/json"
"fmt"
"log"
"encoding/json"
"coopcloud.tech/abra/pkg/client"
"coopcloud.tech/abra/pkg/upstream/stack"
@ -11,34 +13,37 @@ import (
configPkg "coopcloud.tech/abra/pkg/config"
deployPkg "coopcloud.tech/abra/pkg/deploy"
composetypes "github.com/docker/cli/cli/compose/types"
"net/http"
composetypes "github.com/docker/cli/cli/compose/types"
"coop-cloud-backend/internal"
)
type abraHandler struct{
type abraHandler struct {
mux *http.ServeMux
}
func newAbraHandler() *abraHandler {
h := &abraHandler{
mux: http.NewServeMux(),
}
h.mux.HandleFunc("/apps", func(w http.ResponseWriter, r *http.Request) {
h.mux.HandleFunc("/api/abra/apps", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusOK)
return
return
}
switch r.Method {
case http.MethodGet:
case http.MethodGet:
h.handleListApps(w, r)
default:
http.Error(w, "Method not implemented", http.StatusMethodNotAllowed)
}
})
h.mux.HandleFunc("/apps/{serverId}/{appId}/deploy", func(w http.ResponseWriter, r *http.Request) {
h.mux.HandleFunc("/api/abra/apps/{serverId}/{appId}/deploy", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
@ -47,23 +52,23 @@ func newAbraHandler() *abraHandler {
return
}
switch r.Method{
switch r.Method {
case http.MethodPost:
h.handleDeployApp(w, r, r.PathValue("appId"), r.PathValue("serverId"))
default:
http.Error(w, "Method not implemented", http.StatusMethodNotAllowed)
}
})
h.mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
h.mux.HandleFunc("/api/abra/servers", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusOK)
return
return
}
switch r.Method {
case http.MethodGet:
case http.MethodGet:
h.handleListServers(w, r)
default:
http.Error(w, "Method not implemented", http.StatusMethodNotAllowed)
@ -73,8 +78,8 @@ func newAbraHandler() *abraHandler {
}
func StartAPI() {
h := newAbraHandler()
fmt.Println("Server started on port 3000")
http.ListenAndServe(":3000", h)
log.Println("Server started on port 3000")
log.Fatal(http.ListenAndServe(":3000", h))
}
func (h *abraHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -84,6 +89,7 @@ func (h *abraHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Delegate to internal mux
h.mux.ServeHTTP(w, r)
}
// func (h *appHandler) handleStartApp(w http.ResponseWriter, r *http.Request) {
// appName := r.PathValue("appName")
// w.Write([]byte("starting app: " + appName))
@ -111,7 +117,7 @@ func (h *abraHandler) handleDeployApp(w http.ResponseWriter, r *http.Request, ap
return
}
if deployMeta.IsDeployed {
log.Fatal("%s is already deployed", app.Name)
log.Fatalf("%s is already deployed", app.Name)
InternalServerErrorHandler(w, r)
return
}
@ -204,36 +210,36 @@ func (h *abraHandler) handleDeployApp(w http.ResponseWriter, r *http.Request, ap
//commented code is to show deploy overview before deploy
/*
deployedVersion := configPkg.MISSING_DEFAULT
if deployMeta.IsDeployed {
deployedVersion = deployMeta.Version
if deployMeta.IsChaos {
deployedVersion = deployMeta.ChaosVersion
deployedVersion := configPkg.MISSING_DEFAULT
if deployMeta.IsDeployed {
deployedVersion = deployMeta.Version
if deployMeta.IsChaos {
deployedVersion = deployMeta.ChaosVersion
}
}
ShowUnchanged := false
secretInfo, err := deployPkg.GatherSecretsForDeploy(cl, app, ShowUnchanged)
if err != nil {
log.Fatal(err)
InternalServerErrorHandler(w, r)
return
}
}
ShowUnchanged := false
secretInfo, err := deployPkg.GatherSecretsForDeploy(cl, app, ShowUnchanged)
if err != nil {
log.Fatal(err)
InternalServerErrorHandler(w, r)
return
}
// Gather configs
configInfo, err := deployPkg.GatherConfigsForDeploy(cl, app, compose, app.Env, ShowUnchanged)
if err != nil {
log.Fatal(err)
InternalServerErrorHandler(w, r)
return
}
// Gather configs
configInfo, err := deployPkg.GatherConfigsForDeploy(cl, app, compose, app.Env, ShowUnchanged)
if err != nil {
log.Fatal(err)
InternalServerErrorHandler(w, r)
return
}
// Gather images
imageInfo, err := deployPkg.GatherImagesForDeploy(cl, app, compose, ShowUnchanged)
if err != nil {
log.Fatal(err)
InternalServerErrorHandler(w, r)
return
}*/
// Gather images
imageInfo, err := deployPkg.GatherImagesForDeploy(cl, app, compose, ShowUnchanged)
if err != nil {
log.Fatal(err)
InternalServerErrorHandler(w, r)
return
}*/
stack.WaitTimeout, err = appPkg.GetTimeoutFromLabel(compose, stackName)
if err != nil {
@ -287,7 +293,7 @@ func (h *abraHandler) handleListApps(w http.ResponseWriter, r *http.Request) {
if err != nil {
log.Printf("Error getting app %s: %s\n", appName, err)
InternalServerErrorHandler(w, r)
return
return
}
remoteApps = append(remoteApps, remoteApp)
}
@ -295,7 +301,7 @@ func (h *abraHandler) handleListApps(w http.ResponseWriter, r *http.Request) {
appStatuses, err := GetAppStatuses(remoteApps)
if err != nil {
log.Printf("GetAppStatuses Falied\n")
fmt.Println("Error: ", err)
log.Println("Error: ", err)
InternalServerErrorHandler(w, r)
return
}
@ -345,39 +351,39 @@ func appTransposeUndeployed(app appPkg.App) AbraApp {
version = "unknown"
}
return AbraApp{
AppName: app.Name,
Server: app.Server,
Recipe: app.Recipe.Name,
Domain: app.Domain,
Chaos: "false",
Status: "undeployed",
AppName: app.Name,
Server: app.Server,
Recipe: app.Recipe.Name,
Domain: app.Domain,
Chaos: "false",
Status: "undeployed",
ChaosVersion: "unknown",
Version: version,
Upgrade: "latest",
Version: version,
Upgrade: "latest",
}
}
func appTranspose(app appPkg.App, psInfo map[string]string) AbraApp {
return AbraApp{
AppName: app.Name,
Server: app.Server,
Recipe: app.Recipe.Name,
Domain: app.Domain,
Chaos: psInfo["chaos"],
Status: psInfo["status"],
AppName: app.Name,
Server: app.Server,
Recipe: app.Recipe.Name,
Domain: app.Domain,
Chaos: psInfo["chaos"],
Status: psInfo["status"],
ChaosVersion: getOrDefault(psInfo, "chaosVersion", "unknown"),
Version: psInfo["version"],
Upgrade: "latest",
Version: psInfo["version"],
Upgrade: "latest",
}
}
func getOrDefault(m map[string]string, key, def string) string {
if v, ok := m[key]; ok {
return v
}
return def
if v, ok := m[key]; ok {
return v
}
return def
}
func (h *abraHandler) handleListServers (w http.ResponseWriter, r *http.Request) {
func (h *abraHandler) handleListServers(w http.ResponseWriter, r *http.Request) {
servers, err := GetServers()
if err != nil {
InternalServerErrorHandler(w, r)
@ -390,12 +396,12 @@ func (h *abraHandler) handleListServers (w http.ResponseWriter, r *http.Request)
}
abraServers := make([]AbraServer, 0, len(servers))
for i := range len(servers) {
abraServers = append(abraServers,
AbraServer{
Name: serverNames[i],
Host: servers[i],
},
)
abraServers = append(abraServers,
AbraServer{
Name: serverNames[i],
Host: servers[i],
},
)
}
jsonBytes, err := json.Marshal(abraServers)
if err != nil {

8
app.go
View File

@ -49,7 +49,7 @@ import (
// return envMap, nil
// }
func printApp(app appPkg.App) error {
fmt.Printf("Name: %s | Domain: %s | Server: %s | Path: %s",
log.Printf("Name: %s | Domain: %s | Server: %s | Path: %s",
app.Name, app.Domain, app.Server, app.Path)
return nil
}
@ -64,13 +64,13 @@ func connectToContainer(app appPkg.App, serviceName string) {
filters := filters.NewArgs()
filters.Add("name", stackAndServiceName)
fmt.Printf("HI?")
log.Printf("HI?")
targetContainer, err := containerPkg.GetContainer(context.Background(), cl, filters, false)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Container ID: %s", targetContainer.ID)
log.Printf("Container ID: %s", targetContainer.ID)
}
func main() {
appNames, err := appPkg.GetAppNames()
@ -79,7 +79,7 @@ func main() {
}
for _, appName := range appNames {
val := fmt.Sprintf("app , %v", appName)
fmt.Println(val)
log.Println(val)
}
api.StartAPI()

View File

@ -1,6 +1,5 @@
#!/bin/bash
/backend/app &
/home/node/wizard/gobackend &
cd /frontend
npm run dev
npm run dev -- --host

1
web Submodule

Submodule web added at 08510b136e