feat: write auto-detected port mappings during a deploy

During an app build, we now auto-detect ports based on the source code. This is usually http:80:5000, with Dockerfile-based deploys having their ports extracted from the docker image or Dockerfile. Additionally, we add an https:443 mapping for any detected http:80 mapping when there is an ssl certificate, and all http port mappings are transformed to https mappings for Dockerfile-based deploys.

While the ports aren't currently consumed, a future refactor will provide the ability to fallback to the new detected ports when there is no user-specified port mapping.
This commit is contained in:
Jose Diaz-Gonzalez
2023-07-16 03:35:40 -04:00
parent b44be8def9
commit 4bc3de5540
16 changed files with 246 additions and 10 deletions

View File

@@ -1,5 +1,5 @@
SUBCOMMANDS = subcommands/list subcommands/add subcommands/clear subcommands/remove subcommands/set subcommands/report
TRIGGERS = triggers/install triggers/ports-clear triggers/ports-configure triggers/ports-dockerfile-raw-tcp-ports triggers/ports-get triggers/ports-get-available triggers/post-app-clone-setup triggers/post-app-rename-setup triggers/post-certs-remove triggers/post-certs-update triggers/post-delete triggers/report
TRIGGERS = triggers/install triggers/ports-clear triggers/ports-configure triggers/ports-dockerfile-raw-tcp-ports triggers/ports-get triggers/ports-get-available triggers/ports-set-detected triggers/post-app-clone-setup triggers/post-app-rename-setup triggers/post-certs-remove triggers/post-certs-update triggers/post-delete triggers/report
BUILD = commands subcommands triggers
PLUGIN_NAME = ports

View File

@@ -63,6 +63,54 @@ func getAvailablePort() int {
}
}
func getDetectedPortMaps(appName string) []PortMap {
defaultMapping := []PortMap{
{
ContainerPort: 5000,
HostPort: 80,
Scheme: "http",
},
}
portMaps := []PortMap{}
value, err := common.PropertyListGet("ports", appName, "map-detected")
if err == nil {
portMaps, _ = parsePortMapString(strings.Join(value, " "))
}
if len(portMaps) == 0 {
portMaps = defaultMapping
}
if doesCertExist(appName) {
setSSLPort := false
for _, portMap := range portMaps {
if portMap.Scheme != "http" || portMap.HostPort != 80 {
continue
}
setSSLPort = true
portMaps = append(portMaps, PortMap{
ContainerPort: portMap.ContainerPort,
HostPort: 443,
Scheme: "https",
})
}
if !setSSLPort {
for i, portMap := range portMaps {
if portMap.Scheme != "http" {
continue
}
portMaps[i].Scheme = "https"
}
}
}
return portMaps
}
func getDockerfileRawTCPPorts(appName string) []int {
b, _ := common.PlugnTriggerOutput("config-get", []string{appName, "DOKKU_DOCKERFILE_PORTS"}...)
dockerfilePorts := strings.TrimSpace(string(b[:]))

View File

@@ -13,7 +13,8 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
}
flags := map[string]common.ReportFunc{
"--ports-map": reportPortMap,
"--ports-map": reportPortMap,
"--ports-map-detected": reportPortMapDetected,
}
flagKeys := []string{}
@@ -35,3 +36,12 @@ func reportPortMap(appName string) string {
return strings.Join(portMaps, " ")
}
func reportPortMapDetected(appName string) string {
var portMaps []string
for _, portMap := range getDetectedPortMaps(appName) {
portMaps = append(portMaps, portMap.String())
}
return strings.Join(portMaps, " ")
}

View File

@@ -34,6 +34,10 @@ func main() {
err = ports.TriggerPortsGet(appName)
case "ports-get-available":
err = ports.TriggerPortsGetAvailable()
case "ports-set-detected":
appName := flag.Arg(0)
appName, portMapString := common.ShiftString(flag.Args())
err = ports.TriggerPortsSetDetected(appName, strings.Join(portMapString, " "))
case "post-app-clone-setup":
oldAppName := flag.Arg(0)
newAppName := flag.Arg(1)

View File

@@ -2,6 +2,7 @@ package ports
import (
"fmt"
"sort"
"github.com/dokku/dokku/plugins/common"
"github.com/dokku/dokku/plugins/config"
@@ -101,6 +102,23 @@ func TriggerPortsGetAvailable() error {
return nil
}
// TriggerPortsGetAvailable prints out an available port greater than 1024
func TriggerPortsSetDetected(appName string, portMapString string) error {
portMaps, _ := parsePortMapString(portMapString)
var value []string
for _, portMap := range uniquePortMaps(portMaps) {
if portMap.AllowsPersistence() {
continue
}
value = append(value, portMap.String())
}
sort.Strings(value)
return common.PropertyListWrite("ports", appName, "map-detected", value)
}
// TriggerPostAppCloneSetup creates new ports files
func TriggerPostAppCloneSetup(oldAppName string, newAppName string) error {
err := common.PropertyClone("ports", oldAppName, newAppName)