detached 5dc0e41

Merge branch 'dev'

commit
5dc0e4156bcb6bdf58e4dda89014cc7e016ab18b
author
bamen · · 2024-10-16 08:57 UTC
merge of
b05cd54 + 2966ef2 · diff against the first parent
signature
unsigned
44 files · +213 -1679
M .vscode/launch.json +1 -1
@@ -9,7 +9,7 @@
99 "type": "go",
1010 "request": "launch",
1111 "mode": "debug",
12- "program": "./cmd/cli/main.go",
12+ "program": "./main.go",
1313 }
1414
1515
@@ -9,7 +9,7 @@
9 "type": "go",9 "type": "go",
10 "request": "launch",10 "request": "launch",
11 "mode": "debug",11 "mode": "debug",
12- "program": "./cmd/cli/main.go",12+ "program": "./main.go",
13 }13 }
14 14
15 15
M Makefile +56 -11
@@ -1,19 +1,64 @@
1+# This Makefile is used for dev purposes
12 # Variables
2-INSTALL_DIR = /usr/bin
3-BINARY_NAME = gordon
3+REPO := ghcr.io/bnema/gordon
4+TAG := dev
5+DIST_DIR := ./dist
6+ENGINE := podman
7+
8+# Architectures
9+ARCHS := amd64 arm64
10+
11+# Phony targets
12+.PHONY: all build build-push clean
13+
414 # Default target
515 all: build
616
7-# Build the Go binary
17+# Build binaries
818 build:
9- go build -o $(BINARY_NAME) cmd/cli/main.go
19+ @echo "Building Go binaries..."
20+ @mkdir -p $(DIST_DIR)
21+ @rm -f $(DIST_DIR)/*
22+ @CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(DIST_DIR)/gordon-linux-amd64 ./main.go
23+ @CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(DIST_DIR)/gordon-linux-arm64 ./main.go
24+ @echo "Go binaries built successfully"
1025
11-# Install the binary to /usr/local/bin
12-install:
13- mv $(BINARY_NAME) $(INSTALL_DIR)
26+# Build and push Docker images
27+build-push: build
28+ @echo "Cleaning up dangling images..."
29+ @$(ENGINE) image prune -f
1430
15-# Clean up the built binary
16-clean:
17- rm -f $(BINARY_NAME)
31+ @echo "Building and pushing Docker images..."
32+ @for arch in $(ARCHS); do \
33+ cp $(DIST_DIR)/gordon-linux-$$arch gordon; \
34+ $(ENGINE) build -t $(REPO):$(TAG)-$$arch .; \
35+ rm gordon; \
36+ $(ENGINE) push $(REPO):$(TAG)-$$arch; \
37+ done
38+
39+ @echo "Removing existing manifest..."
40+ @$(ENGINE) manifest rm $(REPO):$(TAG) || true
41+
42+ @echo "Creating multi-arch manifest..."
43+ @$(ENGINE) manifest create $(REPO):$(TAG) \
44+ $(REPO):$(TAG)-amd64 \
45+ $(REPO):$(TAG)-arm64
1846
19-.PHONY: all build install clean⏎̸
47+ @echo "Annotating arm64 image..."
48+ @$(ENGINE) manifest annotate $(REPO):$(TAG) \
49+ $(REPO):$(TAG)-arm64 --arch arm64 --variant v8
50+
51+ @echo "Inspecting manifest..."
52+ @$(ENGINE) manifest inspect $(REPO):$(TAG)
53+
54+ @echo "Pushing multi-arch manifest..."
55+ @$(ENGINE) manifest push --all $(REPO):$(TAG)
56+
57+ @echo "Script completed successfully."
58+
59+# Clean up
60+clean:
61+ @echo "Cleaning up..."
62+ @rm -rf $(DIST_DIR)
63+ @$(ENGINE) system prune -f
64+ @echo "Cleanup completed."⏎̸
@@ -1,19 +1,64 @@
1+# This Makefile is used for dev purposes
1 # Variables2 # Variables
2-INSTALL_DIR = /usr/bin3+REPO := ghcr.io/bnema/gordon
3-BINARY_NAME = gordon 4+TAG := dev
5+DIST_DIR := ./dist
6+ENGINE := podman
7+
8+# Architectures
9+ARCHS := amd64 arm64
10+
11+# Phony targets
12+.PHONY: all build build-push clean
13+
4 # Default target14 # Default target
5 all: build15 all: build
6 16
7-# Build the Go binary17+# Build binaries
8 build:18 build:
9- go build -o $(BINARY_NAME) cmd/cli/main.go19+ @echo "Building Go binaries..."
20+ @mkdir -p $(DIST_DIR)
21+ @rm -f $(DIST_DIR)/*
22+ @CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(DIST_DIR)/gordon-linux-amd64 ./main.go
23+ @CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(DIST_DIR)/gordon-linux-arm64 ./main.go
24+ @echo "Go binaries built successfully"
10 25
11-# Install the binary to /usr/local/bin26+# Build and push Docker images
12-install:27+build-push: build
13- mv $(BINARY_NAME) $(INSTALL_DIR)28+ @echo "Cleaning up dangling images..."
29+ @$(ENGINE) image prune -f
14 30
15-# Clean up the built binary31+ @echo "Building and pushing Docker images..."
16-clean:32+ @for arch in $(ARCHS); do \
17- rm -f $(BINARY_NAME)33+ cp $(DIST_DIR)/gordon-linux-$$arch gordon; \
34+ $(ENGINE) build -t $(REPO):$(TAG)-$$arch .; \
35+ rm gordon; \
36+ $(ENGINE) push $(REPO):$(TAG)-$$arch; \
37+ done
38+
39+ @echo "Removing existing manifest..."
40+ @$(ENGINE) manifest rm $(REPO):$(TAG) || true
41+
42+ @echo "Creating multi-arch manifest..."
43+ @$(ENGINE) manifest create $(REPO):$(TAG) \
44+ $(REPO):$(TAG)-amd64 \
45+ $(REPO):$(TAG)-arm64
18 46
19-.PHONY: all build install clean⏎̸47+ @echo "Annotating arm64 image..."
48+ @$(ENGINE) manifest annotate $(REPO):$(TAG) \
49+ $(REPO):$(TAG)-arm64 --arch arm64 --variant v8
50+
51+ @echo "Inspecting manifest..."
52+ @$(ENGINE) manifest inspect $(REPO):$(TAG)
53+
54+ @echo "Pushing multi-arch manifest..."
55+ @$(ENGINE) manifest push --all $(REPO):$(TAG)
56+
57+ @echo "Script completed successfully."
58+
59+# Clean up
60+clean:
61+ @echo "Cleaning up..."
62+ @rm -rf $(DIST_DIR)
63+ @$(ENGINE) system prune -f
64+ @echo "Cleanup completed."⏎̸
M assets/vhs/demo_deploy.tape +1 -1
@@ -60,7 +60,7 @@ Require curl
6060
6161 Set TypingSpeed 75ms
6262 Set Shell "bash"
63-Set FontSize 17
63+Set FontSize 16
6464 Set FontFamily "FiraCode Nerd Font"
6565 Set Width 1200
6666 Set Height 500
@@ -60,7 +60,7 @@ Require curl
60 60
61 Set TypingSpeed 75ms61 Set TypingSpeed 75ms
62 Set Shell "bash"62 Set Shell "bash"
63-Set FontSize 1763+Set FontSize 16
64 Set FontFamily "FiraCode Nerd Font"64 Set FontFamily "FiraCode Nerd Font"
65 Set Width 120065 Set Width 1200
66 Set Height 50066 Set Height 500
D build-dev.sh +0 -20
@@ -1,20 +0,0 @@
1-#!/bin/bash
2-
3-set -e
4-
5-REPO="ghcr.io/bnema/gordon"
6-TAG="dev"
7-DIST_DIR="./dist"
8-
9-# Ensure dist directory exists
10-mkdir -p $DIST_DIR
11-
12-# Clean up previous builds
13-rm -f $DIST_DIR/*
14-
15-# Build Go binaries for multiple platforms with CGO_ENABLED=0
16-echo "Building Go binaries..."
17-CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $DIST_DIR/gordon-linux-amd64 ./main.go
18-CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $DIST_DIR/gordon-linux-arm64 ./main.go
19-
20-echo "Successfully built Go binaries"
@@ -1,20 +0,0 @@
1-#!/bin/bash
2-
3-set -e
4-
5-REPO="ghcr.io/bnema/gordon"
6-TAG="dev"
7-DIST_DIR="./dist"
8-
9-# Ensure dist directory exists
10-mkdir -p $DIST_DIR
11-
12-# Clean up previous builds
13-rm -f $DIST_DIR/*
14-
15-# Build Go binaries for multiple platforms with CGO_ENABLED=0
16-echo "Building Go binaries..."
17-CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $DIST_DIR/gordon-linux-amd64 ./main.go
18-CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $DIST_DIR/gordon-linux-arm64 ./main.go
19-
20-echo "Successfully built Go binaries"
D buildpush-dev.sh +0 -71
@@ -1,71 +0,0 @@
1-#!/bin/bash
2-set -e
3-ENGINE="podman"
4-REPO="ghcr.io/bnema/gordon"
5-TAG="dev"
6-DIST_DIR="./dist"
7-
8-# Function to handle errors
9-handle_error() {
10- echo "Error occurred. Cleaning up..."
11- $ENGINE system prune -f
12- exit 1
13-}
14-
15-# Set up error handling
16-trap 'handle_error' ERR
17-
18-# Ensure dist directory exists
19-mkdir -p $DIST_DIR
20-
21-# Build Go binaries for multiple platforms with CGO_ENABLED=0
22-echo "Building Go binaries..."
23-CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $DIST_DIR/gordon-linux-amd64 ./main.go
24-CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $DIST_DIR/gordon-linux-arm64 ./main.go
25-
26-# Clean up any dangling images before building
27-echo "Cleaning up dangling images..."
28-$ENGINE image prune -f
29-
30-# Build Docker images for each architecture
31-echo "Building Docker images..."
32-for ARCH in amd64 arm64; do
33- # Copy the appropriate binary to the root directory and rename it to 'gordon'
34- cp $DIST_DIR/gordon-linux-$ARCH gordon
35-
36- # Build the Docker image
37- $ENGINE build -t $REPO:${TAG}-$ARCH .
38-
39- # Remove the temporary 'gordon' file
40- rm gordon
41-done
42-
43-# Push images
44-echo "Pushing Docker images..."
45-$ENGINE push $REPO:${TAG}-amd64
46-$ENGINE push $REPO:${TAG}-arm64
47-
48-# Remove existing manifest if it exists
49-echo "Removing existing manifest..."
50-$ENGINE manifest rm $REPO:$TAG || true
51-
52-# Create multi-arch manifest
53-echo "Creating multi-arch manifest..."
54-$ENGINE manifest create $REPO:$TAG \
55- $REPO:${TAG}-amd64 \
56- $REPO:${TAG}-arm64
57-
58-# Annotate the arm64 image with variant information
59-echo "Annotating arm64 image..."
60-$ENGINE manifest annotate $REPO:$TAG \
61- $REPO:${TAG}-arm64 --arch arm64 --variant v8
62-
63-# Debug: List manifests
64-echo "Listing manifests..."
65-$ENGINE manifest inspect $REPO:$TAG
66-
67-# Push multi-arch manifest
68-echo "Pushing multi-arch manifest..."
69-$ENGINE manifest push --all $REPO:$TAG
70-
71-echo "Script completed successfully."
@@ -1,71 +0,0 @@
1-#!/bin/bash
2-set -e
3-ENGINE="podman"
4-REPO="ghcr.io/bnema/gordon"
5-TAG="dev"
6-DIST_DIR="./dist"
7-
8-# Function to handle errors
9-handle_error() {
10- echo "Error occurred. Cleaning up..."
11- $ENGINE system prune -f
12- exit 1
13-}
14-
15-# Set up error handling
16-trap 'handle_error' ERR
17-
18-# Ensure dist directory exists
19-mkdir -p $DIST_DIR
20-
21-# Build Go binaries for multiple platforms with CGO_ENABLED=0
22-echo "Building Go binaries..."
23-CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $DIST_DIR/gordon-linux-amd64 ./main.go
24-CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $DIST_DIR/gordon-linux-arm64 ./main.go
25-
26-# Clean up any dangling images before building
27-echo "Cleaning up dangling images..."
28-$ENGINE image prune -f
29-
30-# Build Docker images for each architecture
31-echo "Building Docker images..."
32-for ARCH in amd64 arm64; do
33- # Copy the appropriate binary to the root directory and rename it to 'gordon'
34- cp $DIST_DIR/gordon-linux-$ARCH gordon
35-
36- # Build the Docker image
37- $ENGINE build -t $REPO:${TAG}-$ARCH .
38-
39- # Remove the temporary 'gordon' file
40- rm gordon
41-done
42-
43-# Push images
44-echo "Pushing Docker images..."
45-$ENGINE push $REPO:${TAG}-amd64
46-$ENGINE push $REPO:${TAG}-arm64
47-
48-# Remove existing manifest if it exists
49-echo "Removing existing manifest..."
50-$ENGINE manifest rm $REPO:$TAG || true
51-
52-# Create multi-arch manifest
53-echo "Creating multi-arch manifest..."
54-$ENGINE manifest create $REPO:$TAG \
55- $REPO:${TAG}-amd64 \
56- $REPO:${TAG}-arm64
57-
58-# Annotate the arm64 image with variant information
59-echo "Annotating arm64 image..."
60-$ENGINE manifest annotate $REPO:$TAG \
61- $REPO:${TAG}-arm64 --arch arm64 --variant v8
62-
63-# Debug: List manifests
64-echo "Listing manifests..."
65-$ENGINE manifest inspect $REPO:$TAG
66-
67-# Push multi-arch manifest
68-echo "Pushing multi-arch manifest..."
69-$ENGINE manifest push --all $REPO:$TAG
70-
71-echo "Script completed successfully."
M internal/cli/cmd/deploy.go +4 -2
@@ -116,7 +116,7 @@ func exportDockerImage(imageName string) (io.ReadCloser, int64, error) {
116116
117117 func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain string) error {
118118
119- log.Info("Attempting to deploy...", "image", imageName, "port", port, "target_domain", targetDomain)
119+ log.Info("Attempting to deploy...", "image", imageName, "port", port, "target", targetDomain)
120120
121121 reqPayload := common.RequestPayload{
122122 Type: "deploy",
@@ -172,6 +172,8 @@ func waitForDeployment(domain string, containerID string) error {
172172 client := &http.Client{Timeout: 10 * time.Second}
173173 maxRetries := 20
174174 retryInterval := time.Second
175+ // shorten the container id to 12 characters
176+ shortContainerID := containerID[:12]
175177
176178 log.Info("Waiting for deployment to be reachable")
177179 for i := 0; i < maxRetries; i++ {
@@ -181,7 +183,7 @@ func waitForDeployment(domain string, containerID string) error {
181183 if resp.StatusCode == http.StatusOK {
182184 log.Info("Deployment successful",
183185 "domain", domain,
184- "container_id", containerID)
186+ "container_id", shortContainerID)
185187 return nil
186188 }
187189 // Check for error messages in the response body
@@ -116,7 +116,7 @@ func exportDockerImage(imageName string) (io.ReadCloser, int64, error) {
116 116
117 func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain string) error {117 func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain string) error {
118 118
119- log.Info("Attempting to deploy...", "image", imageName, "port", port, "target_domain", targetDomain)119+ log.Info("Attempting to deploy...", "image", imageName, "port", port, "target", targetDomain)
120 120
121 reqPayload := common.RequestPayload{121 reqPayload := common.RequestPayload{
122 Type: "deploy",122 Type: "deploy",
@@ -172,6 +172,8 @@ func waitForDeployment(domain string, containerID string) error {
172 client := &http.Client{Timeout: 10 * time.Second}172 client := &http.Client{Timeout: 10 * time.Second}
173 maxRetries := 20173 maxRetries := 20
174 retryInterval := time.Second174 retryInterval := time.Second
175+ // shorten the container id to 12 characters
176+ shortContainerID := containerID[:12]
175 177
176 log.Info("Waiting for deployment to be reachable")178 log.Info("Waiting for deployment to be reachable")
177 for i := 0; i < maxRetries; i++ {179 for i := 0; i < maxRetries; i++ {
@@ -181,7 +183,7 @@ func waitForDeployment(domain string, containerID string) error {
181 if resp.StatusCode == http.StatusOK {183 if resp.StatusCode == http.StatusOK {
182 log.Info("Deployment successful",184 log.Info("Deployment successful",
183 "domain", domain,185 "domain", domain,
184- "container_id", containerID)186+ "container_id", shortContainerID)
185 return nil187 return nil
186 }188 }
187 // Check for error messages in the response body189 // Check for error messages in the response body
M internal/cli/cmd/push.go +12 -5
@@ -4,6 +4,7 @@ import (
44 "encoding/json"
55 "fmt"
66 "os"
7+ "strings"
78
89 "github.com/bnema/gordon/internal/cli"
910 "github.com/bnema/gordon/internal/cli/handler"
@@ -73,22 +74,28 @@ func pushImage(a *cli.App, imageName string) error {
7374
7475 resp, err := handler.SendHTTPRequest(a, &reqPayload, "POST", "/push")
7576 if err != nil {
76- return fmt.Errorf("error sending HTTP request: %w", err)
77+ log.Error("Error sending HTTP request", "error", err)
78+ return err
7779 }
7880
7981 var pushResponse common.PushResponse
8082 if err := json.Unmarshal(resp.Body, &pushResponse); err != nil {
81- return fmt.Errorf("error parsing response: %w", err)
83+ log.Error("Error parsing response", "error", err)
84+ return err
8285 }
8386
8487 if !pushResponse.Success {
85- return fmt.Errorf("push failed: %s", pushResponse.Message)
88+ log.Error("Push failed", "resp", pushResponse.Message)
89+ return fmt.Errorf(pushResponse.Message)
8690 }
8791
88- log.Info("Image pushed successfully", "image", imageName)
92+ //Remove the double quotes from the message
93+ message := strings.Trim(pushResponse.Message, "\"")
94+
95+ log.Info(message)
8996
9097 if pushResponse.CreateContainerURL != "" {
91- log.Info("Container creation URL:", "url", pushResponse.CreateContainerURL)
98+ log.Info("Container creation available", "url", pushResponse.CreateContainerURL)
9299 }
93100
94101 return nil
@@ -4,6 +4,7 @@ import (
4 "encoding/json"4 "encoding/json"
5 "fmt"5 "fmt"
6 "os"6 "os"
7+ "strings"
7 8
8 "github.com/bnema/gordon/internal/cli"9 "github.com/bnema/gordon/internal/cli"
9 "github.com/bnema/gordon/internal/cli/handler"10 "github.com/bnema/gordon/internal/cli/handler"
@@ -73,22 +74,28 @@ func pushImage(a *cli.App, imageName string) error {
73 74
74 resp, err := handler.SendHTTPRequest(a, &reqPayload, "POST", "/push")75 resp, err := handler.SendHTTPRequest(a, &reqPayload, "POST", "/push")
75 if err != nil {76 if err != nil {
76- return fmt.Errorf("error sending HTTP request: %w", err)77+ log.Error("Error sending HTTP request", "error", err)
78+ return err
77 }79 }
78 80
79 var pushResponse common.PushResponse81 var pushResponse common.PushResponse
80 if err := json.Unmarshal(resp.Body, &pushResponse); err != nil {82 if err := json.Unmarshal(resp.Body, &pushResponse); err != nil {
81- return fmt.Errorf("error parsing response: %w", err)83+ log.Error("Error parsing response", "error", err)
84+ return err
82 }85 }
83 86
84 if !pushResponse.Success {87 if !pushResponse.Success {
85- return fmt.Errorf("push failed: %s", pushResponse.Message)88+ log.Error("Push failed", "resp", pushResponse.Message)
89+ return fmt.Errorf(pushResponse.Message)
86 }90 }
87 91
88- log.Info("Image pushed successfully", "image", imageName)92+ //Remove the double quotes from the message
93+ message := strings.Trim(pushResponse.Message, "\"")
94+
95+ log.Info(message)
89 96
90 if pushResponse.CreateContainerURL != "" {97 if pushResponse.CreateContainerURL != "" {
91- log.Info("Container creation URL:", "url", pushResponse.CreateContainerURL)98+ log.Info("Container creation available", "url", pushResponse.CreateContainerURL)
92 }99 }
93 100
94 return nil101 return nil
R internal/cli/handler/fieldcheck.go → internal/cli/handler/field_check.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/cli/handler/pingrequest.go → internal/cli/handler/ping_request.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/cli/handler/regexcheck.go → internal/cli/handler/regex_check.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/cli/handler/startserver.go → internal/cli/handler/start_server.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/cli/newclient.go → internal/cli/new_client.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/common/initconfig.go → internal/common/init_config.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/common/initdockerclient.go → internal/common/init_dockerclient.go +0 -0 renamed, 100% similar

renamed, 100% similar

M internal/common/payload.go +63 -1
@@ -3,19 +3,21 @@ package common
33 import (
44 "encoding/json"
55 "fmt"
6-
76 "io"
87 )
98
9+// RequestPayload represents the structure of incoming requests
1010 type RequestPayload struct {
1111 Type string `json:"type"`
1212 Payload Payload `json:"payload"`
1313 }
1414
15+// Payload is an interface for different types of payloads
1516 type Payload interface {
1617 GetType() string
1718 }
1819
20+// DeployResponse represents the response structure for deployment requests
1921 type DeployResponse struct {
2022 Success bool `json:"success"`
2123 Message string `json:"message"`
@@ -23,22 +25,26 @@ type DeployResponse struct {
2325 ContainerID string `json:"container_id,omitempty"`
2426 }
2527
28+// PushResponse represents the response structure for push requests
2629 type PushResponse struct {
2730 Success bool `json:"success"`
2831 Message string `json:"message"`
2932 CreateContainerURL string `json:"create_container_url,omitempty"`
3033 }
3134
35+// DeploymentError represents an error that occurred during deployment
3236 type DeploymentError struct {
3337 StatusCode int `json:"status"`
3438 Message string `json:"message"`
3539 RawResponse string `json:"raw_response"`
3640 }
3741
42+// Error implements the error interface for DeploymentError
3843 func (e *DeploymentError) Error() string {
3944 return fmt.Sprintf("Deployment failed (status %d): %s", e.StatusCode, e.Message)
4045 }
4146
47+// DeployPayload represents the payload for deployment requests
4248 type DeployPayload struct {
4349 Port string `json:"port"`
4450 TargetDomain string `json:"targetdomain"`
@@ -47,12 +53,14 @@ type DeployPayload struct {
4753 Data io.ReadCloser
4854 }
4955
56+// PushPayload represents the payload for push requests
5057 type PushPayload struct {
5158 ImageName string `json:"imagename"`
5259 ImageID string `json:"imageid"`
5360 Data io.ReadCloser
5461 }
5562
63+// UnmarshalJSON custom unmarshaler for RequestPayload
5664 func (p *RequestPayload) UnmarshalJSON(data []byte) error {
5765 var raw map[string]json.RawMessage
5866 err := json.Unmarshal(data, &raw)
@@ -64,6 +72,7 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
6472 return err
6573 }
6674
75+ // Unmarshal the payload based on the type
6776 switch p.Type {
6877 case "ping":
6978 var payload PingPayload
@@ -83,6 +92,24 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
8392 return err
8493 }
8594 p.Payload = payload
95+ case "stop":
96+ var payload StopPayload
97+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
98+ return err
99+ }
100+ p.Payload = payload
101+ case "start":
102+ var payload StartPayload
103+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
104+ return err
105+ }
106+ p.Payload = payload
107+ case "remove":
108+ var payload RemovePayload
109+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
110+ return err
111+ }
112+ p.Payload = payload
86113 default:
87114 return fmt.Errorf("invalid type: %s", p.Type)
88115 }
@@ -90,22 +117,27 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
90117 return nil
91118 }
92119
120+// PingPayload represents the payload for ping requests
93121 type PingPayload struct {
94122 Message string `json:"message"`
95123 }
96124
125+// GetType returns the type of the PingPayload
97126 func (p PingPayload) GetType() string {
98127 return "ping"
99128 }
100129
130+// GetType returns the type of the DeployPayload
101131 func (p DeployPayload) GetType() string {
102132 return "deploy"
103133 }
104134
135+// GetType returns the type of the PushPayload
105136 func (p PushPayload) GetType() string {
106137 return "push"
107138 }
108139
140+// NewPingPayload creates a new PingPayload from a map of data
109141 func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
110142 message, ok := data["message"].(string)
111143 if !ok {
@@ -113,3 +145,33 @@ func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
113145 }
114146 return PingPayload{Message: message}, nil
115147 }
148+
149+// StopPayload represents the payload for stop requests
150+type StopPayload struct {
151+ ContainerID string `json:"container_id"`
152+}
153+
154+// GetType returns the type of the StopPayload
155+func (p StopPayload) GetType() string {
156+ return "stop"
157+}
158+
159+// StartPayload represents the payload for start requests
160+type StartPayload struct {
161+ ContainerID string `json:"container_id"`
162+}
163+
164+// GetType returns the type of the StartPayload
165+func (p StartPayload) GetType() string {
166+ return "start"
167+}
168+
169+// RemovePayload represents the payload for remove requests
170+type RemovePayload struct {
171+ ContainerID string `json:"container_id"`
172+}
173+
174+// GetType returns the type of the RemovePayload
175+func (p RemovePayload) GetType() string {
176+ return "remove"
177+}
@@ -3,19 +3,21 @@ package common
3 import (3 import (
4 "encoding/json"4 "encoding/json"
5 "fmt"5 "fmt"
6-
7 "io"6 "io"
8 )7 )
9 8
9+// RequestPayload represents the structure of incoming requests
10 type RequestPayload struct {10 type RequestPayload struct {
11 Type string `json:"type"`11 Type string `json:"type"`
12 Payload Payload `json:"payload"`12 Payload Payload `json:"payload"`
13 }13 }
14 14
15+// Payload is an interface for different types of payloads
15 type Payload interface {16 type Payload interface {
16 GetType() string17 GetType() string
17 }18 }
18 19
20+// DeployResponse represents the response structure for deployment requests
19 type DeployResponse struct {21 type DeployResponse struct {
20 Success bool `json:"success"`22 Success bool `json:"success"`
21 Message string `json:"message"`23 Message string `json:"message"`
@@ -23,22 +25,26 @@ type DeployResponse struct {
23 ContainerID string `json:"container_id,omitempty"`25 ContainerID string `json:"container_id,omitempty"`
24 }26 }
25 27
28+// PushResponse represents the response structure for push requests
26 type PushResponse struct {29 type PushResponse struct {
27 Success bool `json:"success"`30 Success bool `json:"success"`
28 Message string `json:"message"`31 Message string `json:"message"`
29 CreateContainerURL string `json:"create_container_url,omitempty"`32 CreateContainerURL string `json:"create_container_url,omitempty"`
30 }33 }
31 34
35+// DeploymentError represents an error that occurred during deployment
32 type DeploymentError struct {36 type DeploymentError struct {
33 StatusCode int `json:"status"`37 StatusCode int `json:"status"`
34 Message string `json:"message"`38 Message string `json:"message"`
35 RawResponse string `json:"raw_response"`39 RawResponse string `json:"raw_response"`
36 }40 }
37 41
42+// Error implements the error interface for DeploymentError
38 func (e *DeploymentError) Error() string {43 func (e *DeploymentError) Error() string {
39 return fmt.Sprintf("Deployment failed (status %d): %s", e.StatusCode, e.Message)44 return fmt.Sprintf("Deployment failed (status %d): %s", e.StatusCode, e.Message)
40 }45 }
41 46
47+// DeployPayload represents the payload for deployment requests
42 type DeployPayload struct {48 type DeployPayload struct {
43 Port string `json:"port"`49 Port string `json:"port"`
44 TargetDomain string `json:"targetdomain"`50 TargetDomain string `json:"targetdomain"`
@@ -47,12 +53,14 @@ type DeployPayload struct {
47 Data io.ReadCloser53 Data io.ReadCloser
48 }54 }
49 55
56+// PushPayload represents the payload for push requests
50 type PushPayload struct {57 type PushPayload struct {
51 ImageName string `json:"imagename"`58 ImageName string `json:"imagename"`
52 ImageID string `json:"imageid"`59 ImageID string `json:"imageid"`
53 Data io.ReadCloser60 Data io.ReadCloser
54 }61 }
55 62
63+// UnmarshalJSON custom unmarshaler for RequestPayload
56 func (p *RequestPayload) UnmarshalJSON(data []byte) error {64 func (p *RequestPayload) UnmarshalJSON(data []byte) error {
57 var raw map[string]json.RawMessage65 var raw map[string]json.RawMessage
58 err := json.Unmarshal(data, &raw)66 err := json.Unmarshal(data, &raw)
@@ -64,6 +72,7 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
64 return err72 return err
65 }73 }
66 74
75+ // Unmarshal the payload based on the type
67 switch p.Type {76 switch p.Type {
68 case "ping":77 case "ping":
69 var payload PingPayload78 var payload PingPayload
@@ -83,6 +92,24 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
83 return err92 return err
84 }93 }
85 p.Payload = payload94 p.Payload = payload
95+ case "stop":
96+ var payload StopPayload
97+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
98+ return err
99+ }
100+ p.Payload = payload
101+ case "start":
102+ var payload StartPayload
103+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
104+ return err
105+ }
106+ p.Payload = payload
107+ case "remove":
108+ var payload RemovePayload
109+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
110+ return err
111+ }
112+ p.Payload = payload
86 default:113 default:
87 return fmt.Errorf("invalid type: %s", p.Type)114 return fmt.Errorf("invalid type: %s", p.Type)
88 }115 }
@@ -90,22 +117,27 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
90 return nil117 return nil
91 }118 }
92 119
120+// PingPayload represents the payload for ping requests
93 type PingPayload struct {121 type PingPayload struct {
94 Message string `json:"message"`122 Message string `json:"message"`
95 }123 }
96 124
125+// GetType returns the type of the PingPayload
97 func (p PingPayload) GetType() string {126 func (p PingPayload) GetType() string {
98 return "ping"127 return "ping"
99 }128 }
100 129
130+// GetType returns the type of the DeployPayload
101 func (p DeployPayload) GetType() string {131 func (p DeployPayload) GetType() string {
102 return "deploy"132 return "deploy"
103 }133 }
104 134
135+// GetType returns the type of the PushPayload
105 func (p PushPayload) GetType() string {136 func (p PushPayload) GetType() string {
106 return "push"137 return "push"
107 }138 }
108 139
140+// NewPingPayload creates a new PingPayload from a map of data
109 func NewPingPayload(data map[string]interface{}) (PingPayload, error) {141 func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
110 message, ok := data["message"].(string)142 message, ok := data["message"].(string)
111 if !ok {143 if !ok {
@@ -113,3 +145,33 @@ func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
113 }145 }
114 return PingPayload{Message: message}, nil146 return PingPayload{Message: message}, nil
115 }147 }
148+
149+// StopPayload represents the payload for stop requests
150+type StopPayload struct {
151+ ContainerID string `json:"container_id"`
152+}
153+
154+// GetType returns the type of the StopPayload
155+func (p StopPayload) GetType() string {
156+ return "stop"
157+}
158+
159+// StartPayload represents the payload for start requests
160+type StartPayload struct {
161+ ContainerID string `json:"container_id"`
162+}
163+
164+// GetType returns the type of the StartPayload
165+func (p StartPayload) GetType() string {
166+ return "start"
167+}
168+
169+// RemovePayload represents the payload for remove requests
170+type RemovePayload struct {
171+ ContainerID string `json:"container_id"`
172+}
173+
174+// GetType returns the type of the RemovePayload
175+func (p RemovePayload) GetType() string {
176+ return "remove"
177+}
R internal/db/dbstruct.go → internal/db/db_struct.go +0 -0 renamed, 100% similar

renamed, 100% similar

D internal/httpserve/handler/htmx.go +0 -1
@@ -1,1 +0,0 @@
1-package handler
@@ -1,1 +0,0 @@
1-package handler
R internal/httpserve/handler/admin-view.go → internal/httpserve/handlers/admin_view.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/cli-endpoints.go → internal/httpserve/handlers/cli_endpoints.go +16 -16 renamed, 91% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "encoding/json"
@@ -89,7 +89,7 @@ func PostPush(c echo.Context, a *server.App) error {
8989
9090 return sendJSONResponse(c, http.StatusOK, common.PushResponse{
9191 Success: true,
92- Message: "Image pushed successfully",
92+ Message: "Image pushed and imported successfully",
9393 CreateContainerURL: createContainerURL,
9494 })
9595 }
@@ -101,7 +101,7 @@ func validateAndPreparePayload(c echo.Context) (*common.PushPayload, error) {
101101 }
102102
103103 if payload.ImageName == "" {
104- return nil, errors.New("Invalid image name")
104+ return nil, errors.New("invalid image name")
105105 }
106106
107107 return payload, nil
@@ -116,22 +116,22 @@ func saveAndImportImage(c echo.Context, a *server.App, payload *common.PushPaylo
116116
117117 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)
118118 if err != nil {
119- return "", fmt.Errorf("Failed to save image: %v", err)
119+ return "", fmt.Errorf("failed to save image: %v", err)
120120 }
121121
122122 imageID, err := docker.ImportImageToEngine(imagePath)
123123 if err != nil {
124124 store.RemoveFromStorage(imagePath)
125- return "", fmt.Errorf("Failed to import image: %v", err)
125+ return "", fmt.Errorf("failed to import image: %v", err)
126126 }
127127
128128 if imageID == "" {
129- return "", errors.New("Imported image ID is empty")
129+ return "", errors.New("imported image ID is empty")
130130 }
131131
132132 err = store.RemoveFromStorage(imagePath)
133133 if err != nil {
134- return "", fmt.Errorf("Failed to remove temporary image file: %v", err)
134+ return "", fmt.Errorf("failed to remove temporary image file: %v", err)
135135 }
136136
137137 payload.ImageID = imageID
@@ -207,7 +207,7 @@ func PostDeploy(c echo.Context, a *server.App) error {
207207
208208 return sendJSONResponse(c, http.StatusConflict, DeployResponse{
209209 Success: false,
210- Message: fmt.Sprintf("A container for this deploy already exists."),
210+ Message: "A container for this deploy already exists.",
211211 ContainerID: extractedID,
212212 })
213213 }
@@ -253,7 +253,7 @@ func validateAndPrepareDeployPayload(c echo.Context) (*common.DeployPayload, err
253253 }
254254
255255 if payload.ImageName == "" {
256- return nil, errors.New("Invalid image name")
256+ return nil, errors.New("invalid image name")
257257 }
258258
259259 payload.Port = normalizePort(payload.Port)
@@ -287,22 +287,22 @@ func saveAndImportDeployImage(c echo.Context, a *server.App, payload *common.Dep
287287
288288 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)
289289 if err != nil {
290- return "", fmt.Errorf("Failed to save image: %v", err)
290+ return "", fmt.Errorf("failed to save image: %v", err)
291291 }
292292
293293 imageID, err := docker.ImportImageToEngine(imagePath)
294294 if err != nil {
295295 store.RemoveFromStorage(imagePath)
296- return "", fmt.Errorf("Failed to import image: %v", err)
296+ return "", fmt.Errorf("failed to import image: %v", err)
297297 }
298298
299299 if imageID == "" {
300- return "", errors.New("Imported image ID is empty")
300+ return "", errors.New("imported image ID is empty")
301301 }
302302
303303 err = store.RemoveFromStorage(imagePath)
304304 if err != nil {
305- return "", fmt.Errorf("Failed to remove temporary image file: %v", err)
305+ return "", fmt.Errorf("failed to remove temporary image file: %v", err)
306306 }
307307
308308 payload.ImageID = imageID
@@ -313,18 +313,18 @@ func saveAndImportDeployImage(c echo.Context, a *server.App, payload *common.Dep
313313 func createAndStartContainer(a *server.App, payload *common.DeployPayload) (string, error) {
314314 params, err := cmdparams.FromPayloadStructToCmdParams(payload, a, payload.ImageID)
315315 if err != nil {
316- return "", fmt.Errorf("Failed to create command parameters: %v", err)
316+ return "", fmt.Errorf("failed to create command parameters: %v", err)
317317 }
318318
319319 containerID, err := docker.CreateContainer(params)
320320 if err != nil {
321- return "", fmt.Errorf("Failed to create container: %v", err)
321+ return "", fmt.Errorf("failed to create container: %v", err)
322322 }
323323
324324 err = docker.StartContainer(containerID)
325325 if err != nil {
326326 docker.RemoveContainer(containerID)
327- return "", fmt.Errorf("Failed to start container: %v", err)
327+ return "", fmt.Errorf("failed to start container: %v", err)
328328 }
329329
330330 return containerID, nil
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "encoding/json"4 "encoding/json"
@@ -89,7 +89,7 @@ func PostPush(c echo.Context, a *server.App) error {
89 89
90 return sendJSONResponse(c, http.StatusOK, common.PushResponse{90 return sendJSONResponse(c, http.StatusOK, common.PushResponse{
91 Success: true,91 Success: true,
92- Message: "Image pushed successfully",92+ Message: "Image pushed and imported successfully",
93 CreateContainerURL: createContainerURL,93 CreateContainerURL: createContainerURL,
94 })94 })
95 }95 }
@@ -101,7 +101,7 @@ func validateAndPreparePayload(c echo.Context) (*common.PushPayload, error) {
101 }101 }
102 102
103 if payload.ImageName == "" {103 if payload.ImageName == "" {
104- return nil, errors.New("Invalid image name")104+ return nil, errors.New("invalid image name")
105 }105 }
106 106
107 return payload, nil107 return payload, nil
@@ -116,22 +116,22 @@ func saveAndImportImage(c echo.Context, a *server.App, payload *common.PushPaylo
116 116
117 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)117 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)
118 if err != nil {118 if err != nil {
119- return "", fmt.Errorf("Failed to save image: %v", err)119+ return "", fmt.Errorf("failed to save image: %v", err)
120 }120 }
121 121
122 imageID, err := docker.ImportImageToEngine(imagePath)122 imageID, err := docker.ImportImageToEngine(imagePath)
123 if err != nil {123 if err != nil {
124 store.RemoveFromStorage(imagePath)124 store.RemoveFromStorage(imagePath)
125- return "", fmt.Errorf("Failed to import image: %v", err)125+ return "", fmt.Errorf("failed to import image: %v", err)
126 }126 }
127 127
128 if imageID == "" {128 if imageID == "" {
129- return "", errors.New("Imported image ID is empty")129+ return "", errors.New("imported image ID is empty")
130 }130 }
131 131
132 err = store.RemoveFromStorage(imagePath)132 err = store.RemoveFromStorage(imagePath)
133 if err != nil {133 if err != nil {
134- return "", fmt.Errorf("Failed to remove temporary image file: %v", err)134+ return "", fmt.Errorf("failed to remove temporary image file: %v", err)
135 }135 }
136 136
137 payload.ImageID = imageID137 payload.ImageID = imageID
@@ -207,7 +207,7 @@ func PostDeploy(c echo.Context, a *server.App) error {
207 207
208 return sendJSONResponse(c, http.StatusConflict, DeployResponse{208 return sendJSONResponse(c, http.StatusConflict, DeployResponse{
209 Success: false,209 Success: false,
210- Message: fmt.Sprintf("A container for this deploy already exists."),210+ Message: "A container for this deploy already exists.",
211 ContainerID: extractedID,211 ContainerID: extractedID,
212 })212 })
213 }213 }
@@ -253,7 +253,7 @@ func validateAndPrepareDeployPayload(c echo.Context) (*common.DeployPayload, err
253 }253 }
254 254
255 if payload.ImageName == "" {255 if payload.ImageName == "" {
256- return nil, errors.New("Invalid image name")256+ return nil, errors.New("invalid image name")
257 }257 }
258 258
259 payload.Port = normalizePort(payload.Port)259 payload.Port = normalizePort(payload.Port)
@@ -287,22 +287,22 @@ func saveAndImportDeployImage(c echo.Context, a *server.App, payload *common.Dep
287 287
288 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)288 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)
289 if err != nil {289 if err != nil {
290- return "", fmt.Errorf("Failed to save image: %v", err)290+ return "", fmt.Errorf("failed to save image: %v", err)
291 }291 }
292 292
293 imageID, err := docker.ImportImageToEngine(imagePath)293 imageID, err := docker.ImportImageToEngine(imagePath)
294 if err != nil {294 if err != nil {
295 store.RemoveFromStorage(imagePath)295 store.RemoveFromStorage(imagePath)
296- return "", fmt.Errorf("Failed to import image: %v", err)296+ return "", fmt.Errorf("failed to import image: %v", err)
297 }297 }
298 298
299 if imageID == "" {299 if imageID == "" {
300- return "", errors.New("Imported image ID is empty")300+ return "", errors.New("imported image ID is empty")
301 }301 }
302 302
303 err = store.RemoveFromStorage(imagePath)303 err = store.RemoveFromStorage(imagePath)
304 if err != nil {304 if err != nil {
305- return "", fmt.Errorf("Failed to remove temporary image file: %v", err)305+ return "", fmt.Errorf("failed to remove temporary image file: %v", err)
306 }306 }
307 307
308 payload.ImageID = imageID308 payload.ImageID = imageID
@@ -313,18 +313,18 @@ func saveAndImportDeployImage(c echo.Context, a *server.App, payload *common.Dep
313 func createAndStartContainer(a *server.App, payload *common.DeployPayload) (string, error) {313 func createAndStartContainer(a *server.App, payload *common.DeployPayload) (string, error) {
314 params, err := cmdparams.FromPayloadStructToCmdParams(payload, a, payload.ImageID)314 params, err := cmdparams.FromPayloadStructToCmdParams(payload, a, payload.ImageID)
315 if err != nil {315 if err != nil {
316- return "", fmt.Errorf("Failed to create command parameters: %v", err)316+ return "", fmt.Errorf("failed to create command parameters: %v", err)
317 }317 }
318 318
319 containerID, err := docker.CreateContainer(params)319 containerID, err := docker.CreateContainer(params)
320 if err != nil {320 if err != nil {
321- return "", fmt.Errorf("Failed to create container: %v", err)321+ return "", fmt.Errorf("failed to create container: %v", err)
322 }322 }
323 323
324 err = docker.StartContainer(containerID)324 err = docker.StartContainer(containerID)
325 if err != nil {325 if err != nil {
326 docker.RemoveContainer(containerID)326 docker.RemoveContainer(containerID)
327- return "", fmt.Errorf("Failed to start container: %v", err)327+ return "", fmt.Errorf("failed to start container: %v", err)
328 }328 }
329 329
330 return containerID, nil330 return containerID, nil
R internal/httpserve/handler/createcontainer.go → internal/httpserve/handlers/container_crud.go +2 -1 renamed, 98% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -57,6 +57,7 @@ func CreateContainerGET(c echo.Context, a *server.App) error {
5757 "ImageName": imageName,
5858 }
5959
60+ // Render the create container page
6061 rendererData, err := render.GetHTMLRenderer("html/fragments", "createcontainer.gohtml", a.TemplateFS, a)
6162
6263 if err != nil {
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
@@ -57,6 +57,7 @@ func CreateContainerGET(c echo.Context, a *server.App) error {
57 "ImageName": imageName,57 "ImageName": imageName,
58 }58 }
59 59
60+ // Render the create container page
60 rendererData, err := render.GetHTMLRenderer("html/fragments", "createcontainer.gohtml", a.TemplateFS, a)61 rendererData, err := render.GetHTMLRenderer("html/fragments", "createcontainer.gohtml", a.TemplateFS, a)
61 62
62 if err != nil {63 if err != nil {
R internal/httpserve/handler/containers.go → internal/httpserve/handlers/container_management.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/editcontainer.go → internal/httpserve/handlers/container_transactions.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/oauth.go → internal/httpserve/handlers/login.go +16 -14 renamed, 92% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "encoding/base64"
@@ -13,6 +13,7 @@ import (
1313 "github.com/bnema/gordon/internal/db/queries"
1414 "github.com/bnema/gordon/internal/server"
1515 "github.com/bnema/gordon/internal/templating/render"
16+ "github.com/charmbracelet/log"
1617 "github.com/gorilla/sessions"
1718 _ "github.com/joho/godotenv/autoload"
1819 "github.com/labstack/echo-contrib/session"
@@ -59,58 +60,59 @@ func RenderLoginPage(c echo.Context, a *server.App) error {
5960 }
6061
6162 // StartOAuthGithub starts the Github OAuth flow.
63+
6264 func StartOAuthGithub(c echo.Context, a *server.App) error {
63- fmt.Println("Attempting to get an existing session.")
65+ log.Info("Attempting to get an existing session.")
6466 sess, err := getSession(c)
6567 if err != nil || sess == nil || sess.Values == nil {
66- fmt.Println("Session retrieval failed, initiating new GitHub OAuth flow.")
68+ log.Info("Session retrieval failed, initiating new GitHub OAuth flow.")
6769 return initiateGithubOAuthFlow(c, a)
6870 }
6971
70- fmt.Println("Attempting to assert session values.")
72+ log.Info("Attempting to assert session values.")
7173 sessionID, ok1 := sess.Values["sessionID"].(string)
7274 accountID, ok2 := sess.Values["accountID"].(string)
7375 authenticated, ok3 := sess.Values["authenticated"].(bool)
7476
7577 if !ok1 || !ok2 || !ok3 || !authenticated {
76- fmt.Println("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")
78+ log.Info("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")
7779 return initiateGithubOAuthFlow(c, a)
7880 }
7981
80- fmt.Println("Checking if session exists in DB.")
82+ log.Info("Checking if session exists in DB.")
8183 sessionExists, err := queries.CheckDBSessionExists(a, sessionID)
8284 if err != nil {
83- fmt.Printf("Error checking if session exists: %v\n", err)
85+ log.Info("Error checking if session exists", "error", err)
8486 return fmt.Errorf("could not check if session exists: %w", err)
8587 }
8688
8789 if !sessionExists {
88- fmt.Println("Session does not exist in DB, initiating new OAuth flow.")
90+ log.Info("Session does not exist in DB, initiating new OAuth flow.")
8991 return initiateGithubOAuthFlow(c, a)
9092 }
9193
92- fmt.Println("Getting the expiration time of the session.")
94+ log.Info("Getting the expiration time of the session.")
9395 currentTime := time.Now()
9496 sessionExpiration, err := queries.GetSessionExpiration(a, accountID, sessionID, currentTime)
9597 if err != nil {
96- fmt.Printf("Error getting session expiration: %v\n", err)
98+ log.Info("Error getting session expiration", "error", err)
9799 return fmt.Errorf("could not get session expiration: %w", err)
98100 }
99101
100102 if currentTime.After(sessionExpiration) {
101- fmt.Println("Current time is after session expiration, initiating new OAuth flow.")
103+ log.Info("Current time is after session expiration, initiating new OAuth flow.")
102104 return initiateGithubOAuthFlow(c, a)
103105 }
104106
105- fmt.Println("Extending session expiration time by 30 minutes.")
107+ log.Info("Extending session expiration time by 30 minutes.")
106108 newExpirationTime := currentTime.Add(30 * time.Minute)
107109 err = queries.ExtendSessionExpiration(a, accountID, sessionID, newExpirationTime)
108110 if err != nil {
109- fmt.Printf("Error extending session expiration: %v\n", err)
111+ log.Info("Error extending session expiration", "error", err)
110112 return fmt.Errorf("could not extend session expiration: %w", err)
111113 }
112114
113- fmt.Println("Session is valid and extended. Redirecting to admin panel.")
115+ log.Info("Session is valid and extended. Redirecting to admin panel.")
114116 return c.Redirect(http.StatusFound, a.Config.Admin.Path)
115117 }
116118
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "encoding/base64"4 "encoding/base64"
@@ -13,6 +13,7 @@ import (
13 "github.com/bnema/gordon/internal/db/queries"13 "github.com/bnema/gordon/internal/db/queries"
14 "github.com/bnema/gordon/internal/server"14 "github.com/bnema/gordon/internal/server"
15 "github.com/bnema/gordon/internal/templating/render"15 "github.com/bnema/gordon/internal/templating/render"
16+ "github.com/charmbracelet/log"
16 "github.com/gorilla/sessions"17 "github.com/gorilla/sessions"
17 _ "github.com/joho/godotenv/autoload"18 _ "github.com/joho/godotenv/autoload"
18 "github.com/labstack/echo-contrib/session"19 "github.com/labstack/echo-contrib/session"
@@ -59,58 +60,59 @@ func RenderLoginPage(c echo.Context, a *server.App) error {
59 }60 }
60 61
61 // StartOAuthGithub starts the Github OAuth flow.62 // StartOAuthGithub starts the Github OAuth flow.
63+
62 func StartOAuthGithub(c echo.Context, a *server.App) error {64 func StartOAuthGithub(c echo.Context, a *server.App) error {
63- fmt.Println("Attempting to get an existing session.")65+ log.Info("Attempting to get an existing session.")
64 sess, err := getSession(c)66 sess, err := getSession(c)
65 if err != nil || sess == nil || sess.Values == nil {67 if err != nil || sess == nil || sess.Values == nil {
66- fmt.Println("Session retrieval failed, initiating new GitHub OAuth flow.")68+ log.Info("Session retrieval failed, initiating new GitHub OAuth flow.")
67 return initiateGithubOAuthFlow(c, a)69 return initiateGithubOAuthFlow(c, a)
68 }70 }
69 71
70- fmt.Println("Attempting to assert session values.")72+ log.Info("Attempting to assert session values.")
71 sessionID, ok1 := sess.Values["sessionID"].(string)73 sessionID, ok1 := sess.Values["sessionID"].(string)
72 accountID, ok2 := sess.Values["accountID"].(string)74 accountID, ok2 := sess.Values["accountID"].(string)
73 authenticated, ok3 := sess.Values["authenticated"].(bool)75 authenticated, ok3 := sess.Values["authenticated"].(bool)
74 76
75 if !ok1 || !ok2 || !ok3 || !authenticated {77 if !ok1 || !ok2 || !ok3 || !authenticated {
76- fmt.Println("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")78+ log.Info("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")
77 return initiateGithubOAuthFlow(c, a)79 return initiateGithubOAuthFlow(c, a)
78 }80 }
79 81
80- fmt.Println("Checking if session exists in DB.")82+ log.Info("Checking if session exists in DB.")
81 sessionExists, err := queries.CheckDBSessionExists(a, sessionID)83 sessionExists, err := queries.CheckDBSessionExists(a, sessionID)
82 if err != nil {84 if err != nil {
83- fmt.Printf("Error checking if session exists: %v\n", err)85+ log.Info("Error checking if session exists", "error", err)
84 return fmt.Errorf("could not check if session exists: %w", err)86 return fmt.Errorf("could not check if session exists: %w", err)
85 }87 }
86 88
87 if !sessionExists {89 if !sessionExists {
88- fmt.Println("Session does not exist in DB, initiating new OAuth flow.")90+ log.Info("Session does not exist in DB, initiating new OAuth flow.")
89 return initiateGithubOAuthFlow(c, a)91 return initiateGithubOAuthFlow(c, a)
90 }92 }
91 93
92- fmt.Println("Getting the expiration time of the session.")94+ log.Info("Getting the expiration time of the session.")
93 currentTime := time.Now()95 currentTime := time.Now()
94 sessionExpiration, err := queries.GetSessionExpiration(a, accountID, sessionID, currentTime)96 sessionExpiration, err := queries.GetSessionExpiration(a, accountID, sessionID, currentTime)
95 if err != nil {97 if err != nil {
96- fmt.Printf("Error getting session expiration: %v\n", err)98+ log.Info("Error getting session expiration", "error", err)
97 return fmt.Errorf("could not get session expiration: %w", err)99 return fmt.Errorf("could not get session expiration: %w", err)
98 }100 }
99 101
100 if currentTime.After(sessionExpiration) {102 if currentTime.After(sessionExpiration) {
101- fmt.Println("Current time is after session expiration, initiating new OAuth flow.")103+ log.Info("Current time is after session expiration, initiating new OAuth flow.")
102 return initiateGithubOAuthFlow(c, a)104 return initiateGithubOAuthFlow(c, a)
103 }105 }
104 106
105- fmt.Println("Extending session expiration time by 30 minutes.")107+ log.Info("Extending session expiration time by 30 minutes.")
106 newExpirationTime := currentTime.Add(30 * time.Minute)108 newExpirationTime := currentTime.Add(30 * time.Minute)
107 err = queries.ExtendSessionExpiration(a, accountID, sessionID, newExpirationTime)109 err = queries.ExtendSessionExpiration(a, accountID, sessionID, newExpirationTime)
108 if err != nil {110 if err != nil {
109- fmt.Printf("Error extending session expiration: %v\n", err)111+ log.Info("Error extending session expiration", "error", err)
110 return fmt.Errorf("could not extend session expiration: %w", err)112 return fmt.Errorf("could not extend session expiration: %w", err)
111 }113 }
112 114
113- fmt.Println("Session is valid and extended. Redirecting to admin panel.")115+ log.Info("Session is valid and extended. Redirecting to admin panel.")
114 return c.Redirect(http.StatusFound, a.Config.Admin.Path)116 return c.Redirect(http.StatusFound, a.Config.Admin.Path)
115 }117 }
116 118
R internal/httpserve/handler/logout.go → internal/httpserve/handlers/logout.go +4 -3 renamed, 89% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -21,8 +21,9 @@ func Logout(c echo.Context, a *server.App) error {
2121 }
2222
2323 // Invalidate the session in the database
24- if sess != nil {
25- err := queries.InvalidateDBSession(a, sess.Values["sessionID"].(string))
24+ sessionID, ok := sess.Values["sessionID"].(string)
25+ if ok {
26+ err := queries.InvalidateDBSession(a, sessionID)
2627 if err != nil {
2728 return fmt.Errorf("failed to invalidate session: %w", err)
2829 }
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
@@ -21,8 +21,9 @@ func Logout(c echo.Context, a *server.App) error {
21 }21 }
22 22
23 // Invalidate the session in the database23 // Invalidate the session in the database
24- if sess != nil {24+ sessionID, ok := sess.Values["sessionID"].(string)
25- err := queries.InvalidateDBSession(a, sess.Values["sessionID"].(string))25+ if ok {
26+ err := queries.InvalidateDBSession(a, sessionID)
26 if err != nil {27 if err != nil {
27 return fmt.Errorf("failed to invalidate session: %w", err)28 return fmt.Errorf("failed to invalidate session: %w", err)
28 }29 }
R internal/httpserve/handler/senderror.go → internal/httpserve/handlers/send_error.go +1 -1 renamed, 96% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "net/http"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "net/http"4 "net/http"
R internal/httpserve/handler/sessiondb.go → internal/httpserve/handlers/session_db.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/static.go → internal/httpserve/handlers/static.go +1 -1 renamed, 98% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "io/fs"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "io/fs"4 "io/fs"
R internal/httpserve/handler/upload-image.go → internal/httpserve/handlers/upload_image.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
M internal/httpserve/middleware/requirelogin.go +2 -2
@@ -4,7 +4,7 @@ import (
44 "net/http"
55 "time"
66
7- "github.com/bnema/gordon/internal/httpserve/handler"
7+ "github.com/bnema/gordon/internal/httpserve/handlers"
88 "github.com/bnema/gordon/internal/server"
99
1010 "github.com/labstack/echo/v4"
@@ -20,7 +20,7 @@ func RequireLogin(a *server.App) echo.MiddlewareFunc {
2020 const maxRetries = 3
2121 var err error
2222 for i := 0; i < maxRetries; i++ {
23- err = handler.ValidateSessionAndUser(c, a)
23+ err = handlers.ValidateSessionAndUser(c, a)
2424 if err == nil {
2525 return next(c)
2626 }
@@ -4,7 +4,7 @@ import (
4 "net/http"4 "net/http"
5 "time"5 "time"
6 6
7- "github.com/bnema/gordon/internal/httpserve/handler"7+ "github.com/bnema/gordon/internal/httpserve/handlers"
8 "github.com/bnema/gordon/internal/server"8 "github.com/bnema/gordon/internal/server"
9 9
10 "github.com/labstack/echo/v4"10 "github.com/labstack/echo/v4"
@@ -20,7 +20,7 @@ func RequireLogin(a *server.App) echo.MiddlewareFunc {
20 const maxRetries = 320 const maxRetries = 3
21 var err error21 var err error
22 for i := 0; i < maxRetries; i++ {22 for i := 0; i < maxRetries; i++ {
23- err = handler.ValidateSessionAndUser(c, a)23+ err = handlers.ValidateSessionAndUser(c, a)
24 if err == nil {24 if err == nil {
25 return next(c)25 return next(c)
26 }26 }
M internal/httpserve/router.go +25 -25
@@ -1,7 +1,7 @@
11 package httpserve
22
33 import (
4- "github.com/bnema/gordon/internal/httpserve/handler"
4+ "github.com/bnema/gordon/internal/httpserve/handlers"
55 "github.com/bnema/gordon/internal/httpserve/middleware"
66 "github.com/bnema/gordon/internal/server"
77 _ "github.com/joho/godotenv/autoload"
@@ -53,45 +53,45 @@ func bindAPIEndpoints(e *echo.Echo, a *server.App) {
5353
5454 // Device flow endpoints (without RequireToken middleware)
5555 apiGroup.POST("/device/code", func(c echo.Context) error {
56- return handler.DeviceCodeRequest(c, a)
56+ return handlers.DeviceCodeRequest(c, a)
5757 })
5858 apiGroup.POST("/device/token", func(c echo.Context) error {
59- return handler.DeviceTokenRequest(c, a)
59+ return handlers.DeviceTokenRequest(c, a)
6060 })
6161
6262 // Other API endpoints that require a token
6363 protectedApiGroup := apiGroup.Group("", middleware.RequireToken(a))
6464 protectedApiGroup.GET("/ping", func(c echo.Context) error {
65- return handler.GetInfos(c, a)
65+ return handlers.GetInfos(c, a)
6666 })
6767 protectedApiGroup.POST("/deploy", func(c echo.Context) error {
68- return handler.PostDeploy(c, a)
68+ return handlers.PostDeploy(c, a)
6969 })
7070 protectedApiGroup.POST("/push", func(c echo.Context) error {
71- return handler.PostPush(c, a)
71+ return handlers.PostPush(c, a)
7272 })
7373 }
7474
7575 // bindStaticRoute bind static path
7676 func bindStaticRoute(e *echo.Echo, a *server.App, path string) {
7777 e.GET(path, func(c echo.Context) error {
78- return handler.StaticRoute(c, a)
78+ return handlers.StaticRoute(c, a)
7979 }, echomid.Gzip())
8080 }
8181
8282 // bindLoginRoute binds all login routes
8383 func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {
8484 e.GET(adminPath+"/login", func(c echo.Context) error {
85- return handler.RenderLoginPage(c, a)
85+ return handlers.RenderLoginPage(c, a)
8686 })
8787 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {
88- return handler.StartOAuthGithub(c, a)
88+ return handlers.StartOAuthGithub(c, a)
8989 })
9090 e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {
91- return handler.OAuthCallback(c, a)
91+ return handlers.OAuthCallback(c, a)
9292 })
9393 e.GET(adminPath+"/logout", func(c echo.Context) error {
94- return handler.Logout(c, a)
94+ return handlers.Logout(c, a)
9595 })
9696 }
9797
@@ -104,10 +104,10 @@ func bindAdminRoute(e *echo.Echo, a *server.App, adminPath string) {
104104 }, middleware.RequireLogin(a))
105105
106106 adminGroup.GET("/manager", func(c echo.Context) error {
107- return handler.AdminManagerRoute(c, a)
107+ return handlers.AdminManagerRoute(c, a)
108108 }, middleware.RequireLogin(a))
109109 adminGroup.GET("/cc/:ID", func(c echo.Context) error {
110- return handler.CreateContainerFullGET(c, a)
110+ return handlers.CreateContainerFullGET(c, a)
111111 }, middleware.RequireLogin(a))
112112 }
113113
@@ -121,52 +121,52 @@ func bindHTMXEndpoints(e *echo.Echo, a *server.App) {
121121
122122 // List all images component
123123 htmxGroup.GET("/image-manager", func(c echo.Context) error {
124- return handler.ImageManagerComponent(c, a)
124+ return handlers.ImageManagerComponent(c, a)
125125 })
126126 // Delete an image
127127 htmxGroup.DELETE("/image-manager/delete/:ID", func(c echo.Context) error {
128- return handler.ImageManagerDelete(c, a)
128+ return handlers.ImageManagerDelete(c, a)
129129 })
130130
131131 // List all containers
132132 htmxGroup.GET("/container-manager", func(c echo.Context) error {
133- return handler.ContainerManagerComponent(c, a)
133+ return handlers.ContainerManagerComponent(c, a)
134134 })
135135 // Stop a container
136136 htmxGroup.POST("/container-manager/stop/:ID", func(c echo.Context) error {
137- return handler.ContainerManagerStop(c, a)
137+ return handlers.ContainerManagerStop(c, a)
138138 })
139139 // Delete a container
140140 htmxGroup.DELETE("/container-manager/delete/:ID", func(c echo.Context) error {
141- return handler.ContainerManagerDelete(c, a)
141+ return handlers.ContainerManagerDelete(c, a)
142142 })
143143 // Start a container
144144 htmxGroup.POST("/container-manager/start/:ID", func(c echo.Context) error {
145- return handler.ContainerManagerStart(c, a)
145+ return handlers.ContainerManagerStart(c, a)
146146 })
147147 // Edit a container view
148148 htmxGroup.GET("/container-manager/edit/:ID", func(c echo.Context) error {
149- return handler.ContainerManagerEditGET(c, a)
149+ return handlers.ContainerManagerEditGET(c, a)
150150 })
151151 // Edit a container action
152152 htmxGroup.POST("/container-manager/edit/:ID", func(c echo.Context) error {
153- return handler.ContainerManagerEditPOST(c, a)
153+ return handlers.ContainerManagerEditPOST(c, a)
154154 })
155155
156156 // Display upload-image component
157157 htmxGroup.GET("/upload-image", func(c echo.Context) error {
158- return handler.UploadImageGETHandler(c, a)
158+ return handlers.UploadImageGETHandler(c, a)
159159 })
160160 // Upload image
161161 htmxGroup.POST("/upload-image", func(c echo.Context) error {
162- return handler.UploadImagePOSTHandler(c, a)
162+ return handlers.UploadImagePOSTHandler(c, a)
163163 })
164164 // Display create-container component
165165 htmxGroup.GET("/create-container/:ID", func(c echo.Context) error {
166- return handler.CreateContainerGET(c, a)
166+ return handlers.CreateContainerGET(c, a)
167167 })
168168 // Create container
169169 htmxGroup.POST("/create-container/:ID", func(c echo.Context) error {
170- return handler.CreateContainerPOST(c, a)
170+ return handlers.CreateContainerPOST(c, a)
171171 })
172172 }
@@ -1,7 +1,7 @@
1 package httpserve1 package httpserve
2 2
3 import (3 import (
4- "github.com/bnema/gordon/internal/httpserve/handler"4+ "github.com/bnema/gordon/internal/httpserve/handlers"
5 "github.com/bnema/gordon/internal/httpserve/middleware"5 "github.com/bnema/gordon/internal/httpserve/middleware"
6 "github.com/bnema/gordon/internal/server"6 "github.com/bnema/gordon/internal/server"
7 _ "github.com/joho/godotenv/autoload"7 _ "github.com/joho/godotenv/autoload"
@@ -53,45 +53,45 @@ func bindAPIEndpoints(e *echo.Echo, a *server.App) {
53 53
54 // Device flow endpoints (without RequireToken middleware)54 // Device flow endpoints (without RequireToken middleware)
55 apiGroup.POST("/device/code", func(c echo.Context) error {55 apiGroup.POST("/device/code", func(c echo.Context) error {
56- return handler.DeviceCodeRequest(c, a)56+ return handlers.DeviceCodeRequest(c, a)
57 })57 })
58 apiGroup.POST("/device/token", func(c echo.Context) error {58 apiGroup.POST("/device/token", func(c echo.Context) error {
59- return handler.DeviceTokenRequest(c, a)59+ return handlers.DeviceTokenRequest(c, a)
60 })60 })
61 61
62 // Other API endpoints that require a token62 // Other API endpoints that require a token
63 protectedApiGroup := apiGroup.Group("", middleware.RequireToken(a))63 protectedApiGroup := apiGroup.Group("", middleware.RequireToken(a))
64 protectedApiGroup.GET("/ping", func(c echo.Context) error {64 protectedApiGroup.GET("/ping", func(c echo.Context) error {
65- return handler.GetInfos(c, a)65+ return handlers.GetInfos(c, a)
66 })66 })
67 protectedApiGroup.POST("/deploy", func(c echo.Context) error {67 protectedApiGroup.POST("/deploy", func(c echo.Context) error {
68- return handler.PostDeploy(c, a)68+ return handlers.PostDeploy(c, a)
69 })69 })
70 protectedApiGroup.POST("/push", func(c echo.Context) error {70 protectedApiGroup.POST("/push", func(c echo.Context) error {
71- return handler.PostPush(c, a)71+ return handlers.PostPush(c, a)
72 })72 })
73 }73 }
74 74
75 // bindStaticRoute bind static path75 // bindStaticRoute bind static path
76 func bindStaticRoute(e *echo.Echo, a *server.App, path string) {76 func bindStaticRoute(e *echo.Echo, a *server.App, path string) {
77 e.GET(path, func(c echo.Context) error {77 e.GET(path, func(c echo.Context) error {
78- return handler.StaticRoute(c, a)78+ return handlers.StaticRoute(c, a)
79 }, echomid.Gzip())79 }, echomid.Gzip())
80 }80 }
81 81
82 // bindLoginRoute binds all login routes82 // bindLoginRoute binds all login routes
83 func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {83 func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {
84 e.GET(adminPath+"/login", func(c echo.Context) error {84 e.GET(adminPath+"/login", func(c echo.Context) error {
85- return handler.RenderLoginPage(c, a)85+ return handlers.RenderLoginPage(c, a)
86 })86 })
87 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {87 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {
88- return handler.StartOAuthGithub(c, a)88+ return handlers.StartOAuthGithub(c, a)
89 })89 })
90 e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {90 e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {
91- return handler.OAuthCallback(c, a)91+ return handlers.OAuthCallback(c, a)
92 })92 })
93 e.GET(adminPath+"/logout", func(c echo.Context) error {93 e.GET(adminPath+"/logout", func(c echo.Context) error {
94- return handler.Logout(c, a)94+ return handlers.Logout(c, a)
95 })95 })
96 }96 }
97 97
@@ -104,10 +104,10 @@ func bindAdminRoute(e *echo.Echo, a *server.App, adminPath string) {
104 }, middleware.RequireLogin(a))104 }, middleware.RequireLogin(a))
105 105
106 adminGroup.GET("/manager", func(c echo.Context) error {106 adminGroup.GET("/manager", func(c echo.Context) error {
107- return handler.AdminManagerRoute(c, a)107+ return handlers.AdminManagerRoute(c, a)
108 }, middleware.RequireLogin(a))108 }, middleware.RequireLogin(a))
109 adminGroup.GET("/cc/:ID", func(c echo.Context) error {109 adminGroup.GET("/cc/:ID", func(c echo.Context) error {
110- return handler.CreateContainerFullGET(c, a)110+ return handlers.CreateContainerFullGET(c, a)
111 }, middleware.RequireLogin(a))111 }, middleware.RequireLogin(a))
112 }112 }
113 113
@@ -121,52 +121,52 @@ func bindHTMXEndpoints(e *echo.Echo, a *server.App) {
121 121
122 // List all images component122 // List all images component
123 htmxGroup.GET("/image-manager", func(c echo.Context) error {123 htmxGroup.GET("/image-manager", func(c echo.Context) error {
124- return handler.ImageManagerComponent(c, a)124+ return handlers.ImageManagerComponent(c, a)
125 })125 })
126 // Delete an image126 // Delete an image
127 htmxGroup.DELETE("/image-manager/delete/:ID", func(c echo.Context) error {127 htmxGroup.DELETE("/image-manager/delete/:ID", func(c echo.Context) error {
128- return handler.ImageManagerDelete(c, a)128+ return handlers.ImageManagerDelete(c, a)
129 })129 })
130 130
131 // List all containers131 // List all containers
132 htmxGroup.GET("/container-manager", func(c echo.Context) error {132 htmxGroup.GET("/container-manager", func(c echo.Context) error {
133- return handler.ContainerManagerComponent(c, a)133+ return handlers.ContainerManagerComponent(c, a)
134 })134 })
135 // Stop a container135 // Stop a container
136 htmxGroup.POST("/container-manager/stop/:ID", func(c echo.Context) error {136 htmxGroup.POST("/container-manager/stop/:ID", func(c echo.Context) error {
137- return handler.ContainerManagerStop(c, a)137+ return handlers.ContainerManagerStop(c, a)
138 })138 })
139 // Delete a container139 // Delete a container
140 htmxGroup.DELETE("/container-manager/delete/:ID", func(c echo.Context) error {140 htmxGroup.DELETE("/container-manager/delete/:ID", func(c echo.Context) error {
141- return handler.ContainerManagerDelete(c, a)141+ return handlers.ContainerManagerDelete(c, a)
142 })142 })
143 // Start a container143 // Start a container
144 htmxGroup.POST("/container-manager/start/:ID", func(c echo.Context) error {144 htmxGroup.POST("/container-manager/start/:ID", func(c echo.Context) error {
145- return handler.ContainerManagerStart(c, a)145+ return handlers.ContainerManagerStart(c, a)
146 })146 })
147 // Edit a container view147 // Edit a container view
148 htmxGroup.GET("/container-manager/edit/:ID", func(c echo.Context) error {148 htmxGroup.GET("/container-manager/edit/:ID", func(c echo.Context) error {
149- return handler.ContainerManagerEditGET(c, a)149+ return handlers.ContainerManagerEditGET(c, a)
150 })150 })
151 // Edit a container action151 // Edit a container action
152 htmxGroup.POST("/container-manager/edit/:ID", func(c echo.Context) error {152 htmxGroup.POST("/container-manager/edit/:ID", func(c echo.Context) error {
153- return handler.ContainerManagerEditPOST(c, a)153+ return handlers.ContainerManagerEditPOST(c, a)
154 })154 })
155 155
156 // Display upload-image component156 // Display upload-image component
157 htmxGroup.GET("/upload-image", func(c echo.Context) error {157 htmxGroup.GET("/upload-image", func(c echo.Context) error {
158- return handler.UploadImageGETHandler(c, a)158+ return handlers.UploadImageGETHandler(c, a)
159 })159 })
160 // Upload image160 // Upload image
161 htmxGroup.POST("/upload-image", func(c echo.Context) error {161 htmxGroup.POST("/upload-image", func(c echo.Context) error {
162- return handler.UploadImagePOSTHandler(c, a)162+ return handlers.UploadImagePOSTHandler(c, a)
163 })163 })
164 // Display create-container component164 // Display create-container component
165 htmxGroup.GET("/create-container/:ID", func(c echo.Context) error {165 htmxGroup.GET("/create-container/:ID", func(c echo.Context) error {
166- return handler.CreateContainerGET(c, a)166+ return handlers.CreateContainerGET(c, a)
167 })167 })
168 // Create container168 // Create container
169 htmxGroup.POST("/create-container/:ID", func(c echo.Context) error {169 htmxGroup.POST("/create-container/:ID", func(c echo.Context) error {
170- return handler.CreateContainerPOST(c, a)170+ return handlers.CreateContainerPOST(c, a)
171 })171 })
172 }172 }
R internal/server/appserver.go → internal/server/app_server.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/server/newserver.go → internal/server/new_server.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/server/sqliteclose.go → internal/server/sqlite_close.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/server/sqliteinit.go → internal/server/sqlite_init.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/server/tokeninit.go → internal/server/token_init.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/templating/cmdparams/fromcli.go → internal/templating/cmdparams/from_cli.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/templating/cmdparams/frominputs.go → internal/templating/cmdparams/from_inputs.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/templating/cmdparams/fromyaml.go → internal/templating/cmdparams/from_yaml.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/templating/load/loadfragment.go → internal/templating/load/fragment.go +0 -0 renamed, 100% similar

renamed, 100% similar

D package-lock.json +0 -1494 generated file: collapsed
M package.json +4 -4
@@ -1,16 +1,16 @@
11 {
22 "devDependencies": {
33 "@catppuccin/tailwindcss": "^0.1.6",
4- "prettier": "^3.0.3",
5- "prettier-plugin-tailwindcss": "^0.5.5",
6- "tailwindcss": "^3.3.3"
4+ "prettier": "^3.3.3",
5+ "prettier-plugin-tailwindcss": "^0.5.14",
6+ "tailwindcss": "^3.4.14"
77 },
88 "scripts": {
99 "build:css": "tailwindcss build src/styles.css -o dist/styles.css",
1010 "dev:css": "tailwindcss -i internal/webui/public/assets/css/custom.css -o internal/webui/public/assets/css/tailwind.css --watch"
1111 },
1212 "dependencies": {
13- "caniuse-lite": "^1.0.30001653",
13+ "caniuse-lite": "^1.0.30001669",
1414 "dotenv": "^16.4.5"
1515 }
1616 }
@@ -1,16 +1,16 @@
1 {1 {
2 "devDependencies": {2 "devDependencies": {
3 "@catppuccin/tailwindcss": "^0.1.6",3 "@catppuccin/tailwindcss": "^0.1.6",
4- "prettier": "^3.0.3",4+ "prettier": "^3.3.3",
5- "prettier-plugin-tailwindcss": "^0.5.5",5+ "prettier-plugin-tailwindcss": "^0.5.14",
6- "tailwindcss": "^3.3.3"6+ "tailwindcss": "^3.4.14"
7 },7 },
8 "scripts": {8 "scripts": {
9 "build:css": "tailwindcss build src/styles.css -o dist/styles.css",9 "build:css": "tailwindcss build src/styles.css -o dist/styles.css",
10 "dev:css": "tailwindcss -i internal/webui/public/assets/css/custom.css -o internal/webui/public/assets/css/tailwind.css --watch"10 "dev:css": "tailwindcss -i internal/webui/public/assets/css/custom.css -o internal/webui/public/assets/css/tailwind.css --watch"
11 },11 },
12 "dependencies": {12 "dependencies": {
13- "caniuse-lite": "^1.0.30001653",13+ "caniuse-lite": "^1.0.30001669",
14 "dotenv": "^16.4.5"14 "dotenv": "^16.4.5"
15 }15 }
16 }16 }
R pkg/sanitize/htmlsanitizer.go → pkg/sanitize/html_sanitizer.go +0 -0 renamed, 100% similar

renamed, 100% similar

R pkg/sqlite/createdb.go → pkg/sqlite/db_create.go +0 -0 renamed, 100% similar

renamed, 100% similar

R pkg/store/storeimages.go → pkg/store/store_images.go +0 -0 renamed, 100% similar

renamed, 100% similar

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