Add TCP/UDP port mapping support
- Add app_ports table for storing port mappings per app - Add Port model with CRUD operations - Add handlers for adding/deleting port mappings - Add ports section to app detail template - Update Docker client to configure port bindings when creating containers - Support both TCP and UDP protocols
This commit is contained in:
@@ -121,6 +121,7 @@ func (h *Handlers) HandleAppDetail() http.HandlerFunc {
|
||||
envVars, _ := application.GetEnvVars(request.Context())
|
||||
labels, _ := application.GetLabels(request.Context())
|
||||
volumes, _ := application.GetVolumes(request.Context())
|
||||
ports, _ := application.GetPorts(request.Context())
|
||||
deployments, _ := application.GetDeployments(
|
||||
request.Context(),
|
||||
recentDeploymentsLimit,
|
||||
@@ -135,6 +136,7 @@ func (h *Handlers) HandleAppDetail() http.HandlerFunc {
|
||||
"EnvVars": envVars,
|
||||
"Labels": labels,
|
||||
"Volumes": volumes,
|
||||
"Ports": ports,
|
||||
"Deployments": deployments,
|
||||
"WebhookURL": webhookURL,
|
||||
"DeployKey": deployKey,
|
||||
@@ -685,6 +687,96 @@ func (h *Handlers) HandleVolumeDelete() http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// HandlePortAdd handles adding a port mapping.
|
||||
func (h *Handlers) HandlePortAdd() http.HandlerFunc {
|
||||
return func(writer http.ResponseWriter, request *http.Request) {
|
||||
appID := chi.URLParam(request, "id")
|
||||
|
||||
application, findErr := models.FindApp(request.Context(), h.db, appID)
|
||||
if findErr != nil || application == nil {
|
||||
http.NotFound(writer, request)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
parseErr := request.ParseForm()
|
||||
if parseErr != nil {
|
||||
http.Error(writer, "Bad Request", http.StatusBadRequest)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
hostPort, containerPort, valid := parsePortValues(
|
||||
request.FormValue("host_port"),
|
||||
request.FormValue("container_port"),
|
||||
)
|
||||
if !valid {
|
||||
http.Redirect(writer, request, "/apps/"+application.ID, http.StatusSeeOther)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
protocol := request.FormValue("protocol")
|
||||
if protocol != "tcp" && protocol != "udp" {
|
||||
protocol = "tcp"
|
||||
}
|
||||
|
||||
port := models.NewPort(h.db)
|
||||
port.AppID = application.ID
|
||||
port.HostPort = hostPort
|
||||
port.ContainerPort = containerPort
|
||||
port.Protocol = models.PortProtocol(protocol)
|
||||
|
||||
saveErr := port.Save(request.Context())
|
||||
if saveErr != nil {
|
||||
h.log.Error("failed to save port", "error", saveErr)
|
||||
}
|
||||
|
||||
http.Redirect(writer, request, "/apps/"+application.ID, http.StatusSeeOther)
|
||||
}
|
||||
}
|
||||
|
||||
// parsePortValues parses and validates host and container port strings.
|
||||
func parsePortValues(hostPortStr, containerPortStr string) (int, int, bool) {
|
||||
hostPort, hostErr := strconv.Atoi(hostPortStr)
|
||||
containerPort, containerErr := strconv.Atoi(containerPortStr)
|
||||
|
||||
if hostErr != nil || containerErr != nil || hostPort <= 0 || containerPort <= 0 {
|
||||
return 0, 0, false
|
||||
}
|
||||
|
||||
return hostPort, containerPort, true
|
||||
}
|
||||
|
||||
// HandlePortDelete handles deleting a port mapping.
|
||||
func (h *Handlers) HandlePortDelete() http.HandlerFunc {
|
||||
return func(writer http.ResponseWriter, request *http.Request) {
|
||||
appID := chi.URLParam(request, "id")
|
||||
portIDStr := chi.URLParam(request, "portID")
|
||||
|
||||
portID, parseErr := strconv.ParseInt(portIDStr, 10, 64)
|
||||
if parseErr != nil {
|
||||
http.NotFound(writer, request)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
port, findErr := models.FindPort(request.Context(), h.db, portID)
|
||||
if findErr != nil || port == nil {
|
||||
http.NotFound(writer, request)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
deleteErr := port.Delete(request.Context())
|
||||
if deleteErr != nil {
|
||||
h.log.Error("failed to delete port", "error", deleteErr)
|
||||
}
|
||||
|
||||
http.Redirect(writer, request, "/apps/"+appID, http.StatusSeeOther)
|
||||
}
|
||||
}
|
||||
|
||||
// formatDeployKey formats an SSH public key with a descriptive comment.
|
||||
// Format: ssh-ed25519 AAAA... upaas-2025-01-15-example.com.
|
||||
func formatDeployKey(pubKey string, createdAt time.Time, host string) string {
|
||||
|
||||
Reference in New Issue
Block a user