0.1.22 4db9699

clientendpoins.go RawHistoryFolder

1package handler
2
3import (
4	"bytes"
5	"fmt"
6	"io"
7	"net/http"
8	"regexp"
9
10	"github.com/bnema/gordon/internal/common"
11	"github.com/bnema/gordon/internal/server"
12	"github.com/bnema/gordon/internal/templating/cmdparams"
13	"github.com/bnema/gordon/pkg/docker"
14	"github.com/bnema/gordon/pkg/store"
15	"github.com/labstack/echo/v4"
16)
17
18type InfoResponse struct {
19	Uptime  string `json:"uptime"`
20	Version string `json:"version"`
21}
22
23func (info *InfoResponse) Populate(a *server.App) {
24	info.Uptime = a.GetUptime()
25	info.Version = a.GetVersionstring()
26}
27
28// Handle GET on /api/ping endpoint
29func GetInfos(c echo.Context, a *server.App) error {
30	body, _ := io.ReadAll(c.Request().Body)
31	c.Request().Body = io.NopCloser(bytes.NewBuffer(body)) // Reset the body
32
33	payload := new(common.RequestPayload)
34	if err := c.Bind(payload); err != nil {
35		fmt.Println("Bind Error:", err)
36		return c.JSON(http.StatusBadRequest, err.Error())
37	}
38
39	if payload.Type != "ping" {
40		return c.JSON(http.StatusBadRequest, "Invalid payload type")
41	}
42
43	pingPayload, ok := payload.Payload.(common.PingPayload)
44	if !ok {
45		return c.JSON(http.StatusBadRequest, "Invalid payload type")
46	}
47	if pingPayload.Message != "ping" {
48		return c.JSON(http.StatusBadRequest, "Invalid payload data")
49	}
50
51	// Prepare and populate the information
52	info := &InfoResponse{}
53	info.Populate(a)
54
55	return c.JSON(http.StatusOK, info)
56
57}
58
59func PostDeploy(c echo.Context, a *server.App) error {
60
61	// Initialize pushPayload object
62	payload := &common.DeployPayload{
63		Ports:        c.Request().Header.Get("X-Ports"),
64		ImageName:    c.Request().Header.Get("X-Image-Name"),
65		TargetDomain: c.Request().Header.Get("X-Target-Domain"),
66	}
67
68	if payload.ImageName == "" {
69		return c.JSON(http.StatusBadRequest, "Invalid image name")
70	}
71
72	imageReader := c.Request().Body
73	defer imageReader.Close()
74
75	// Rename the image to a valid name so that it can be saved (remove user/, :tag and add .tar)
76	imageFileName := payload.ImageName
77	imageFileName = regexp.MustCompile(`^([a-zA-Z0-9\-_.]+\/)?`).ReplaceAllString(imageFileName, "")
78	imageFileName = regexp.MustCompile(`(:[a-zA-Z0-9\-_.]+)?$`).ReplaceAllString(imageFileName, "")
79	imageFileName = imageFileName + ".tar"
80
81	// Check the ports struct, if there is no /tcp, or /udp, add /tcp
82	if !regexp.MustCompile(`\/(tcp|udp)$`).MatchString(payload.Ports) {
83		payload.Ports = payload.Ports + "/tcp"
84	}
85
86	// Check the target domain, if there is no https:// or http://, add https://
87	if !regexp.MustCompile(`^https?:\/\/`).MatchString(payload.TargetDomain) {
88		payload.TargetDomain = "https://" + payload.TargetDomain
89	}
90
91	// Save the image tar in the storage
92	imageFilePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)
93	if err != nil {
94		return sendJsonError(c, err)
95	}
96
97	// Import the tar in docker
98	err = docker.ImportImageToEngine(imageFilePath)
99	if err != nil {
100		return sendJsonError(c, err)
101	}
102
103	// Remove the image from the storage
104	err = store.RemoveFromStorage()
105	if err != nil {
106		return sendJsonError(c, err)
107	}
108
109	// append localhost to the image name since it's a manually imported image and not from a registry
110	payload.ImageName = "localhost/" + payload.ImageName
111
112	// Get the image ID
113	imageID, err := docker.GetImageID(payload.ImageName)
114	if err != nil {
115		return sendJsonError(c, err)
116	}
117
118	// Update the payload with the image ID
119	payload.ImageID = imageID
120
121	// Create the container using cmdparams.FromPayloadStructToCmdParams
122	params, err := cmdparams.FromPayloadStructToCmdParams(payload, a)
123	if err != nil {
124		return sendJsonError(c, err)
125	}
126
127	// Create the container
128	containerID, err := docker.CreateContainer(params)
129	if err != nil {
130		return sendJsonError(c, err)
131	}
132
133	// Start the container
134	err = docker.StartContainer(containerID)
135	if err != nil {
136		return sendJsonError(c, err)
137	}
138
139	// Remove the container if it fails to start
140	defer func() {
141		if err != nil {
142			docker.RemoveContainer(containerID)
143			c.JSON(http.StatusInternalServerError, sendJsonError(c, err))
144			return
145		}
146	}()
147
148	// If we arrive here, send back payload.TargetDomain so the client can test it
149	return c.JSON(http.StatusOK, payload.TargetDomain)
150}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close