diff --git a/docs/appendices/0.31.0-migration-guide.md b/docs/appendices/0.31.0-migration-guide.md index b07d22ca8a1..06f64469943 100644 --- a/docs/appendices/0.31.0-migration-guide.md +++ b/docs/appendices/0.31.0-migration-guide.md @@ -7,6 +7,7 @@ - The `traefik` integration now mounts config to `/data` instead of the path `/acme.json`, fixing permissions issues under certain architectures. To take advantage of the new functionality, the traefik container should be stopped (via `dokku traefik:stop`) and then started (via `dokku traefik:start`). - Users no longer need to clear the `source-image` git property when transitioning from image-based deploys (`git:from-image` and `git:load-image`) to other deployment methods (git push, `git:from-archive`, `git:sync`). - For deploys via the `git:from-image` and `git:load-image` commands, the `CHECKS` file is now extracted from the configured `WORKDIR` property of the image. For all other deploys - git push, `git:from-archive`, `git:sync` - will have the `CHECKS` extracted directly from the source code. The filename in both cases is `CHECKS` and cannot be modified. +- The environment variable `DOKKU_PROXY_PORT_MAP` has been migrated to the properties system. Direct changes to the value will be ignored, and users should interact with port maps via the `ports` plugin. ## Deprecations diff --git a/docs/configuration/environment-variables.md b/docs/configuration/environment-variables.md index e48084557dd..eb8c02b59aa 100644 --- a/docs/configuration/environment-variables.md +++ b/docs/configuration/environment-variables.md @@ -116,7 +116,6 @@ The following config variables have special meanings and can be set in a variety | `DOKKU_PARALLEL_ARGUMENTS`. | none | `dokku config:set` | Allows passing custom arguments to parallel for `ps:*all` commands | | `DOKKU_PROXY_PORT` | automatically assigned | `/etc/environment`
`~dokku/.dokkurc`
`~dokku/.dokkurc/*`
`dokku config:set` | | | `DOKKU_PROXY_SSL_PORT` | automatically assigned | `/etc/environment`
`~dokku/.dokkurc`
`~dokku/.dokkurc/*`
`dokku config:set` | | -| `DOKKU_PROXY_PORT_MAP` | automatically assigned | `dokku ports:add`
`dokku ports:remove`, `dokku ports:clear` | | | `DOKKU_SKIP_ALL_CHECKS` | none | `dokku config:set` | | | `DOKKU_SKIP_CLEANUP` | | `/etc/environment`
`~dokku/.dokkurc`
`~dokku/.dokkurc/*` | When a deploy is triggered, if this is set to a non-empty value, then old docker containers and images will not be removed. | | `DOKKU_SKIP_DEFAULT_CHECKS` | | `dokku config:set` | | diff --git a/docs/networking/port-management.md b/docs/networking/port-management.md index 3fcca069656..f1dc089a445 100644 --- a/docs/networking/port-management.md +++ b/docs/networking/port-management.md @@ -84,8 +84,6 @@ dokku ports:add node-js-app http:8080:5000 ``` ``` ------> Setting config vars - DOKKU_PROXY_PORT_MAP: http:80:5000 http:8080:5000 -----> Configuring node-js-app.dokku.me...(using built-in template) -----> Creating http nginx.conf Reloading nginx @@ -120,8 +118,6 @@ dokku ports:set node-js-app http:8080:5000 ``` ``` ------> Setting config vars - DOKKU_PROXY_PORT_MAP: http:80:5000 http:8080:5000 -----> Configuring node-js-app.dokku.me...(using built-in template) -----> Creating http nginx.conf Reloading nginx diff --git a/docs/networking/proxies/nginx.md b/docs/networking/proxies/nginx.md index a5ec6deec78..5bf70c66bc3 100644 --- a/docs/networking/proxies/nginx.md +++ b/docs/networking/proxies/nginx.md @@ -376,8 +376,8 @@ Unsetting this value is the same as enabling custom nginx config usage. {{ .PROXY_PORT }} Non-SSL nginx listener port (same as `DOKKU_PROXY_PORT` config var) {{ .PROXY_SSL_PORT }} SSL nginx listener port (same as `DOKKU_PROXY_SSL_PORT` config var) {{ .NOSSL_SERVER_NAME }} List of non-SSL VHOSTS -{{ .PROXY_PORT_MAP }} List of port mappings (same as `DOKKU_PROXY_PORT_MAP` config var) -{{ .PROXY_UPSTREAM_PORTS }} List of configured upstream ports (derived from `DOKKU_PROXY_PORT_MAP` config var) +{{ .PROXY_PORT_MAP }} List of port mappings (same as the `port-map` ports property) +{{ .PROXY_UPSTREAM_PORTS }} List of configured upstream ports (derived from the `port-map` ports property) {{ .RAW_TCP_PORTS }} List of exposed tcp ports as defined by Dockerfile `EXPOSE` directive (**Dockerfile apps only**) {{ .SSL_INUSE }} Boolean set when an app is SSL-enabled {{ .SSL_SERVER_NAME }} List of SSL VHOSTS diff --git a/plugins/ports/Makefile b/plugins/ports/Makefile index 189f7b8991b..ac8759b6ed4 100644 --- a/plugins/ports/Makefile +++ b/plugins/ports/Makefile @@ -1,5 +1,5 @@ SUBCOMMANDS = subcommands/list subcommands/add subcommands/clear subcommands/remove subcommands/set subcommands/report -TRIGGERS = triggers/ports-clear triggers/ports-configure triggers/ports-dockerfile-raw-tcp-ports triggers/ports-get triggers/ports-get-available triggers/post-certs-remove triggers/post-certs-update 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/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 diff --git a/plugins/ports/functions.go b/plugins/ports/functions.go index 5c20be0f06b..64b8e9628f3 100644 --- a/plugins/ports/functions.go +++ b/plugins/ports/functions.go @@ -23,10 +23,7 @@ func addPortMaps(appName string, portMaps []PortMap) error { } func clearPorts(appName string) error { - return common.EnvWrap(func() error { - keys := []string{"DOKKU_PROXY_PORT_MAP"} - return config.UnsetMany(appName, keys, false) - }, map[string]string{"DOKKU_QUIET_OUTPUT": "1"}) + return common.PropertyDelete("ports", appName, "port-map") } func doesCertExist(appName string) bool { @@ -118,8 +115,12 @@ func getGlobalProxySSLPort() int { } func getPortMaps(appName string) []PortMap { - value := config.GetWithDefault(appName, "DOKKU_PROXY_PORT_MAP", "") - portMaps, _ := parsePortMapString(value) + value, err := common.PropertyListGet("ports", appName, "port-map") + if err != nil { + return []PortMap{} + } + + portMaps, _ := parsePortMapString(strings.Join(value, " ")) return portMaps } @@ -363,8 +364,7 @@ func removePortMaps(appName string, portMaps []PortMap) error { } if len(toSet) == 0 { - keys := []string{"DOKKU_PROXY_PORT_MAP"} - return config.UnsetMany(appName, keys, false) + return common.PropertyDelete("ports", appName, "port-map") } return setPortMaps(appName, toSet) @@ -380,13 +380,8 @@ func setPortMaps(appName string, portMaps []PortMap) error { value = append(value, portMap.String()) } - return common.EnvWrap(func() error { - sort.Strings(value) - entries := map[string]string{ - "DOKKU_PROXY_PORT_MAP": strings.Join(value, " "), - } - return config.SetMany(appName, entries, false) - }, map[string]string{"DOKKU_QUIET_OUTPUT": "1"}) + sort.Strings(value) + return common.PropertyListWrite("ports", appName, "port-map", value) } func setProxyPort(appName string, port int) error { diff --git a/plugins/ports/src/triggers/triggers.go b/plugins/ports/src/triggers/triggers.go index 6551298da45..f97571120f3 100644 --- a/plugins/ports/src/triggers/triggers.go +++ b/plugins/ports/src/triggers/triggers.go @@ -18,6 +18,8 @@ func main() { var err error switch trigger { + case "install": + err = ports.TriggerInstall() case "ports-clear": appName := flag.Arg(0) err = ports.TriggerPortsClear(appName) @@ -32,12 +34,23 @@ func main() { err = ports.TriggerPortsGet(appName) case "ports-get-available": err = ports.TriggerPortsGetAvailable() + case "post-app-clone-setup": + oldAppName := flag.Arg(0) + newAppName := flag.Arg(1) + err = ports.TriggerPostAppCloneSetup(oldAppName, newAppName) + case "post-app-rename-setup": + oldAppName := flag.Arg(0) + newAppName := flag.Arg(1) + err = ports.TriggerPostAppRenameSetup(oldAppName, newAppName) case "post-certs-remove": appName := flag.Arg(0) err = ports.TriggerPostCertsRemove(appName) case "post-certs-update": appName := flag.Arg(0) err = ports.TriggerPostCertsUpdate(appName) + case "post-delete": + appName := flag.Arg(0) + err = ports.TriggerPostDelete(appName) case "report": appName := flag.Arg(0) err = ports.ReportSingleApp(appName, "", "") diff --git a/plugins/ports/triggers.go b/plugins/ports/triggers.go index d9a8bad3343..e5a9af25758 100644 --- a/plugins/ports/triggers.go +++ b/plugins/ports/triggers.go @@ -7,6 +7,43 @@ import ( "github.com/dokku/dokku/plugins/config" ) +// TriggerInstall migrates the ports config to properties +func TriggerInstall() error { + if err := common.PropertySetup("ports"); err != nil { + return fmt.Errorf("Unable to install the ports plugin: %s", err.Error()) + } + + apps, err := common.UnfilteredDokkuApps() + if err != nil { + return nil + } + + for _, appName := range apps { + if common.PropertyExists("ports", appName, "port-map") { + continue + } + + common.LogInfo1(fmt.Sprintf("Migrating DOKKU_PROXY_PORT_MAP to port-map property for %s", appName)) + portMapString := config.GetWithDefault(appName, "DOKKU_PROXY_PORT_MAP", "") + portMaps, _ := parsePortMapString(portMapString) + + propertyValue := []string{} + for _, portMap := range portMaps { + propertyValue = append(propertyValue, portMap.String()) + } + + if err := common.PropertyListWrite("ports", appName, "port-map", propertyValue); err != nil { + return err + } + + if err := config.UnsetMany(appName, []string{"DOKKU_PROXY_PORT_MAP"}, false); err != nil { + return err + } + } + + return nil +} + // TriggerPortsClear removes all ports for the specified app func TriggerPortsClear(appName string) error { return clearPorts(appName) @@ -64,6 +101,29 @@ func TriggerPortsGetAvailable() error { return nil } +// TriggerPostAppCloneSetup creates new ports files +func TriggerPostAppCloneSetup(oldAppName string, newAppName string) error { + err := common.PropertyClone("ports", oldAppName, newAppName) + if err != nil { + return err + } + + return nil +} + +// TriggerPostAppRenameSetup renames ports files +func TriggerPostAppRenameSetup(oldAppName string, newAppName string) error { + if err := common.PropertyClone("ports", oldAppName, newAppName); err != nil { + return err + } + + if err := common.PropertyDestroy("ports", oldAppName); err != nil { + return err + } + + return nil +} + // TriggerPostCertsRemove unsets port config vars after SSL cert is added func TriggerPostCertsRemove(appName string) error { keys := []string{"DOKKU_PROXY_SSL_PORT"} @@ -129,3 +189,12 @@ func TriggerPostCertsUpdate(appName string) error { return nil } + +// TriggerPostDelete is the ports post-delete plugin trigger +func TriggerPostDelete(appName string) error { + if err := common.PropertyDestroy("ports", appName); err != nil { + common.LogWarn(err.Error()) + } + + return nil +} diff --git a/tests/unit/apps_2.bats b/tests/unit/apps_2.bats index ce91b5e7897..d7a2a2cece0 100644 --- a/tests/unit/apps_2.bats +++ b/tests/unit/apps_2.bats @@ -108,8 +108,23 @@ teardown() { } @test "(apps) apps:clone ssl-app" { - run /bin/bash -c "dokku config:set --no-restart $TEST_APP DOKKU_PROXY_PORT_MAP=https:443:5000 DOKKU_PROXY_SSL_PORT=443" - deploy_app + skip "this test always failed and requires changes in dokku to support detected vs specified functionality" + run /bin/bash -c "dokku apps:create $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + run /bin/bash -c "dokku ports:set $TEST_APP https:443:5000" + echo "output: $output" + echo "status: $status" + assert_success + run /bin/bash -c "dokku config:set --no-restart $TEST_APP DOKKU_PROXY_SSL_PORT=443" + echo "output: $output" + echo "status: $status" + assert_success + run deploy_app + echo "output: $output" + echo "status: $status" + assert_success run /bin/bash -c "dokku apps:clone $TEST_APP app-without-ssl" echo "output: $output" echo "status: $status" diff --git a/tests/unit/nginx-vhosts_3.bats b/tests/unit/nginx-vhosts_3.bats index 0a7ad5fa7c2..6f7a5fbb94b 100644 --- a/tests/unit/nginx-vhosts_3.bats +++ b/tests/unit/nginx-vhosts_3.bats @@ -17,23 +17,61 @@ teardown() { } @test "(nginx-vhosts) grpc endpoint" { - deploy_app gogrpc - dokku ports:add "$TEST_APP" "grpc:80:50051" + run deploy_app gogrpc + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku ports:add $TEST_APP grpc:80:50051" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku nginx:show-config $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + run /bin/bash -c "docker run --rm ${TEST_APP}-docker-image /go/bin/greeter_client -address ${TEST_APP}.dokku.me:80 -name grpc" + echo "output: $output" + echo "status: $status" + assert_success assert_output "Greeting: Hello grpc" } @test "(nginx-vhosts) grpc endpoint on a port other than 80" { - deploy_app gogrpc - dokku ports:add "$TEST_APP" "grpc:8080:50051" + run deploy_app gogrpc + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku ports:add $TEST_APP grpc:8080:50051" + echo "output: $output" + echo "status: $status" + assert_success + run /bin/bash -c "docker run --rm ${TEST_APP}-docker-image /go/bin/greeter_client -address ${TEST_APP}.dokku.me:8080 -name grpc8080" + echo "output: $output" + echo "status: $status" + assert_success assert_output "Greeting: Hello grpc8080" } @test "(nginx-vhosts) grpcs endpoint" { setup_test_tls - deploy_app gogrpc - dokku ports:add "$TEST_APP" "grpcs:443:50051" + run deploy_app gogrpc + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku ports:add $TEST_APP grpcs:443:50051" + echo "output: $output" + echo "status: $status" + assert_success + run /bin/bash -c "docker run --rm ${TEST_APP}-docker-image /go/bin/greeter_client -address ${TEST_APP}.dokku.me:443 -name grpcs -tls" + echo "output: $output" + echo "status: $status" + assert_success assert_output "Greeting: Hello grpcs" }