diff --git a/docs/appendices/0.31.0-migration-guide.md b/docs/appendices/0.31.0-migration-guide.md
index 547cbc6cecb..e818193997c 100644
--- a/docs/appendices/0.31.0-migration-guide.md
+++ b/docs/appendices/0.31.0-migration-guide.md
@@ -1,5 +1,6 @@
-# 0.30.0 Migration Guide
+# 0.31.0 Migration Guide
## Changes
- Herokuish build cache is now mounted from a docker volume - eg. `cache-node-js-app` - instead of the local filesystem. All existing app cache will be cleared upon upgrading past 0.29.0.
+- The `proxy:ports*` commands have been replaced with the new `ports` plugin. Users will be able to use the old `proxy:ports*` commands for a single minor release, and they will be removed in the next minor release.
diff --git a/docs/configuration/environment-variables.md b/docs/configuration/environment-variables.md
index c4498062fe8..e48084557dd 100644
--- a/docs/configuration/environment-variables.md
+++ b/docs/configuration/environment-variables.md
@@ -116,7 +116,7 @@ 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 proxy:ports-add`
`dokku proxy:ports-remove`, `dokku proxy:ports-clear` | |
+| `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/configuration/ssl.md b/docs/configuration/ssl.md
index 42664a7491e..abb0f9f6293 100644
--- a/docs/configuration/ssl.md
+++ b/docs/configuration/ssl.md
@@ -134,7 +134,7 @@ Certain versions of nginx have bugs that prevent [HTTP/2](https://nginx.org/en/d
### SSL Port Exposure
-When your app is served from port `80` then the `/home/dokku/APP/nginx.conf` file will automatically be updated to instruct nginx to respond to ssl on port 443 as a new cert is added. If your app uses a non-standard port (perhaps you have a dockerfile deploy exposing port `99999`) you may need to manually expose an ssl port via `dokku proxy:ports-add https:443:99999`.
+When your app is served from port `80` then the `/home/dokku/APP/nginx.conf` file will automatically be updated to instruct nginx to respond to ssl on port 443 as a new cert is added. If your app uses a non-standard port (perhaps you have a dockerfile deploy exposing port `99999`) you may need to manually expose an ssl port via `dokku ports:add https:443:99999`.
## Other
diff --git a/docs/development/plugin-triggers.md b/docs/development/plugin-triggers.md
index a141b115f71..f74e6afb12c 100644
--- a/docs/development/plugin-triggers.md
+++ b/docs/development/plugin-triggers.md
@@ -1498,8 +1498,8 @@ popd &>/dev/null
### `post-proxy-ports-update`
-- Description: Allows you to run commands once the proxy port mappings for an app have been updated. It also sends the invoking command. This can be "add", "clear" or "remove".
-- Invoked by: `dokku proxy:ports-add`, `dokku proxy:ports-clear`, `dokku proxy:ports-remove`
+- Description: Allows you to run commands once the port mappings for an app have been updated. It also sends the invoking command. This can be "add", "clear" or "remove".
+- Invoked by: `dokku ports:add`, `dokku ports:clear`, `dokku ports:remove`
- Arguments: `$APP` `action name`
- Example:
@@ -1842,7 +1842,7 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
### `proxy-configure-ports`
-- Description: Configures the proxy port mapping
+- Description: Configures the port mapping
- Invoked by: `internally triggered by proxy plugins`
- Arguments: `$APP`
- Example:
diff --git a/docs/getting-started/troubleshooting.md b/docs/getting-started/troubleshooting.md
index e0e4d7b6e78..9677f27b970 100644
--- a/docs/getting-started/troubleshooting.md
+++ b/docs/getting-started/troubleshooting.md
@@ -74,12 +74,12 @@ For example, if you have an `EXPOSE` directive like so:
EXPOSE 8000
```
-The proxy port mapping will be `http:8000:8000`.
+The port mapping will be `http:8000:8000`.
To avoid this issue, either of the following can be done:
-- Remove `EXPOSE` directive: This will require respecting the `$PORT` environment variable (automatically set by Dokku). Once that change is deployed, the port mapping should be cleared via the `dokku proxy:ports-clear $APP` command (where `$APP` is your app name).
-- Update the port mapping: Updating the port mapping to redirect port `80` to your app's exposed port via `dokku proxy:ports-set $APP http:80:$EXPOSED_PORT` can also fix the issue. This will also allow certificate management and the letsencrypt plugin to work correctly.
+- Remove `EXPOSE` directive: This will require respecting the `$PORT` environment variable (automatically set by Dokku). Once that change is deployed, the port mapping should be cleared via the `dokku ports:clear $APP` command (where `$APP` is your app name).
+- Update the port mapping: Updating the port mapping to redirect port `80` to your app's exposed port via `dokku ports:set $APP http:80:$EXPOSED_PORT` can also fix the issue. This will also allow certificate management and the letsencrypt plugin to work correctly.
See the [port management documentation](/docs/networking/port-management.md) for more information on how Dokku exposes ports for applications and how you can configure these for your app.
@@ -235,16 +235,14 @@ If this solves the issue temporarily, longer term you should consider [configuri
### My application deploys properly, but won't load in browser "connection refused"
-This could be a result of a bad proxy configuration (`http:5000:5000` may be incorrect). Run `dokku proxy:report myapp` to check if your app has the correct proxy configuration. It should show something like the following.
+This could be a result of a bad proxy configuration (`http:5000:5000` may be incorrect). Run `dokku ports:report node-js-app` to check if your app has the correct proxy configuration. It should show something like the following.
```
-=====> myapp proxy information
- Proxy enabled: true
- Proxy port map: http:80:5000 https:443:5000
- Proxy type: nginx
+=====> node-js-app ports information
+ Port map: http:80:5000 https:443:5000
```
-Set `dokku proxy:ports-set front http:80:5000` to get proxy correctly configured for http endpoint.
+Set `dokku ports:set node-js-app http:80:5000` to get proxy correctly configured for http endpoint.
### I deployed a new app but now subdomains are miss-routed
diff --git a/docs/networking/port-management.md b/docs/networking/port-management.md
index 9cab146dcf3..3fcca069656 100644
--- a/docs/networking/port-management.md
+++ b/docs/networking/port-management.md
@@ -1,37 +1,52 @@
# Port Management
-> New as of 0.5.0, Enhanced in 0.6.0
+> New as of 0.31.0, replaces the previous `proxy:ports*` commands
```
-proxy:ports # List proxy port mappings for an app
-proxy:ports-add :: [::...] # Add proxy port mappings to an app
-proxy:ports-clear # Clear all proxy port mappings for an app
-proxy:ports-remove [|::...] # Remove specific proxy port mappings from an app
-proxy:ports-set :: [::...] # Set proxy port mappings for an app
+ports:list # List port mappings for an app
+ports:add :: [::...] # Add port mappings to an app
+ports:clear # Clear all port mappings for an app
+ports:remove [|::...] # Remove specific port mappings from an app
+ports:set :: [::...] # Set port mappings for an app
```
-In Dokku 0.5.0, port proxying was decoupled from the `nginx-vhosts` plugin into the proxy plugin. Dokku 0.6.0 introduced the ability to map host ports to specific container ports. In the future this will allow other proxy software - such as HAProxy or Caddy - to be used in place of nginx.
-
## Usage
> Warning: Mapping alternative ports may conflict with the active firewall installed on your server or hosting provider. Such software includes - but is not limited to - AWS Security Groups, iptables, and UFW. Please consult the documentation for those softwares as applicable.
>
> Users should also avoid setting the `PORT` environment variable. Dokku will use port mappings to set this value. Overriding this manually may cause issues in application routing.
-> New as of 0.6.0
-
-You can now configure `host -> container` port mappings with the `proxy:ports-*` commands. This mapping is currently supported by the built-in nginx-vhosts plugin.
+You can now configure `host -> container` port mappings with the `ports:*` commands. This mapping is currently supported by the built-in nginx-vhosts plugin.
By default, buildpack apps and dockerfile apps **without** explicitly exposed ports (i.e. using the `EXPOSE` directive) will be configured with a listener on port `80` (and additionally a listener on 443 if ssl is enabled) that will proxy to the application container on port `5000`. Dockerfile apps **with** explicitly exposed ports will be configured with a listener on each exposed port and will proxy to that same port of the deployed application container.
-> Note: This default behavior **will not** be automatically changed on subsequent pushes and must be manipulated with the `proxy:ports-*` commands detailed below.
+> Note: This default behavior **will not** be automatically changed on subsequent pushes and must be manipulated with the `ports:*` commands detailed below.
+
+### Port Scheme
+
+The proxy port scheme is as follows:
+
+- `SCHEME:HOST_PORT:CONTAINER_PORT`
+
+The scheme metadata can be used by proxy implementations in order to properly handle proxying of requests. For example, the built-in `nginx-vhosts` proxy implementation supports the `http`, `https`, `grpc` and `grpcs` schemes.
+For the `grpc` and `grpcs` see [nginx blog post on grpc](https://www.nginx.com/blog/nginx-1-13-10-grpc/).
+
+Developers of proxy implementations are encouraged to use whatever schemes make the most sense, and ignore configurations which they do not support. For instance, a `udp` proxy implementation can safely ignore `http` and `https` port mappings.
+
+To change the proxy implementation in use for an application, use the `proxy:set` command:
+
+```shell
+# no validation will be performed against
+# the specified proxy implementation
+dokku proxy:set node-js-app nginx
+```
### Listing port mappings
-To inspect the port mapping for a given application, use the `proxy:ports` command:
+To inspect the port mapping for a given application, use the `ports:list` command:
```shell
-dokku proxy:ports node-js-app
+dokku ports:list node-js-app
```
```
@@ -62,10 +77,10 @@ curl http://node-js-app.dokku.me:8080
curl: (7) Failed to connect to node-js-app.dokku.me port 8080: Connection refused
```
-However, we can use the `proxy:ports-add` command to add a second external port mapping - `8080` - to our application's port `5000`.
+However, we can use the `ports:add` command to add a second external port mapping - `8080` - to our application's port `5000`.
```shell
-dokku proxy:ports-add node-js-app http:8080:5000
+dokku ports:add node-js-app http:8080:5000
```
```
@@ -98,10 +113,10 @@ Hello World!
### Setting all port mappings at once
-Port mappings can also be force set using the `proxy:ports-set` command.
+Port mappings can also be force set using the `ports:set` command.
```shell
-dokku proxy:ports-set node-js-app http:8080:5000
+dokku ports:set node-js-app http:8080:5000
```
```
@@ -114,21 +129,21 @@ dokku proxy:ports-set node-js-app http:8080:5000
### Removing a port mapping
-A port mapping can be removed using the `proxy:ports-remove` command if it no longer necessary:
+A port mapping can be removed using the `ports:remove` command if it no longer necessary:
```shell
-dokku proxy:ports-remove node-js-app http:80:5000
+dokku ports:remove node-js-app http:80:5000
```
Ports may also be removed by specifying only the `host-port` value. This effectively acts as a wildcard and removes all mappings for that particular host port.
```shell
-dokku proxy:ports-remove node-js-app http:80
+dokku ports:remove node-js-app http:80
```
## Port management by Deployment Method
-> Warning: If you set a proxy port map but _do not have a global domain set_, Dokku will reset that map upon first deployment.
+> Warning: If you set a port map but _do not have a global domain set_, Dokku will reset that map upon first deployment.
### Buildpacks
@@ -156,10 +171,10 @@ The application would be exposed to the user at `node-js-app.dokku.me:1234`. If
```shell
# add a port mapping to port 80
-dokku proxy:ports-add node-js-app http:80:1234
+dokku ports:add node-js-app http:80:1234
# remove the incorrect port mapping
-dokku proxy:ports-remove node-js-app http:1234:1234
+dokku ports:remove node-js-app http:1234:1234
```
#### Applications not using EXPOSE
@@ -176,7 +191,7 @@ When switching between `EXPOSE` usage modes, it is important to reset your port
```shell
# assuming your application is called `node-js-app`
dokku config:unset --no-restart node-js-app DOKKU_DOCKERFILE_PORTS PORT
-dokku proxy:ports-clear node-js-app
+dokku ports:clear node-js-app
```
### Docker Image
@@ -186,7 +201,41 @@ When deploying an image, we will use `docker inspect` to extract the `ExposedPor
```shell
# assuming your application is called `node-js-app`
dokku config:set node-js-app DOKKU_DOCKERFILE_PORTS="1234/tcp 80/tcp"
-dokku proxy:ports-clear node-js-app
+dokku ports:clear node-js-app
```
All other port-related behavior is the same as when deploying via Dockerfile.
+
+### Displaying ports reports for an app
+
+You can get a report about the app's ports status using the `ports:report` command:
+
+```shell
+dokku ports:report
+```
+
+```
+=====> node-js-app ports information
+ Port map: http:80:5000 https:443:5000
+=====> python-sample ports information
+ Port map: http:80:5000
+=====> ruby-sample ports information
+ Port map: http:80:5000
+```
+
+You can run the command for a specific app also.
+
+```shell
+dokku ports:report node-js-app
+```
+
+```
+=====> node-js-app ports information
+ Port map: http:80:5000 https:443:5000
+```
+
+You can pass flags which will output only the value of the specific information you want. For example:
+
+```shell
+dokku ports:report node-js-app --ports-map
+```
diff --git a/docs/networking/proxies/nginx.md b/docs/networking/proxies/nginx.md
index 1f6213f9f39..a5ec6deec78 100644
--- a/docs/networking/proxies/nginx.md
+++ b/docs/networking/proxies/nginx.md
@@ -506,7 +506,7 @@ See the [proxy documentation](/docs/networking/proxy-management.md) for more inf
### Managing Proxy Port mappings
-See the [proxy documentation](/docs/networking/proxy-management.md#proxy-port-mapping) for more information on how to manage ports proxied for your app.
+See the [ports documentation](/docs/networking/port-management.md) for more information on how to manage ports proxied for your app.
### Regenerating nginx config
diff --git a/docs/networking/proxy-management.md b/docs/networking/proxy-management.md
index a716952fb2b..4366acbe4c3 100644
--- a/docs/networking/proxy-management.md
+++ b/docs/networking/proxy-management.md
@@ -73,15 +73,12 @@ dokku proxy:report
=====> node-js-app proxy information
Proxy enabled: true
Proxy type: nginx
- Proxy port map: http:80:5000 https:443:5000
=====> python-sample proxy information
Proxy enabled: true
Proxy type: nginx
- Proxy port map: http:80:5000
=====> ruby-sample proxy information
Proxy enabled: true
Proxy type: nginx
- Proxy port map: http:80:5000
```
You can run the command for a specific app also.
@@ -94,7 +91,6 @@ dokku proxy:report node-js-app
=====> node-js-app proxy information
Proxy enabled: true
Proxy type: nginx
- Proxy port map: http:80:5000 https:443:5000
```
You can pass flags which will output only the value of the specific information you want. For example:
@@ -105,22 +101,7 @@ dokku proxy:report node-js-app --proxy-type
#### Proxy Port Scheme
-The proxy port scheme is as follows:
-
-- `SCHEME:HOST_PORT:CONTAINER_PORT`
-
-The scheme metadata can be used by proxy implementations in order to properly handle proxying of requests. For example, the built-in `nginx-vhosts` proxy implementation supports the `http`, `https`, `grpc` and `grpcs` schemes.
-For the `grpc` and `grpcs` see [nginx blog post on grpc](https://www.nginx.com/blog/nginx-1-13-10-grpc/).
-
-Developers of proxy implementations are encouraged to use whatever schemes make the most sense, and ignore configurations which they do not support. For instance, a `udp` proxy implementation can safely ignore `http` and `https` port mappings.
-
-To change the proxy implementation in use for an application, use the `proxy:set` command:
-
-```shell
-# no validation will be performed against
-# the specified proxy implementation
-dokku proxy:set node-js-app nginx
-```
+See the [port scheme documentation](/docs/networking/port-management.md#port-scheme) for more information on the port mapping scheme used by dokku.
### Proxy port mapping
@@ -136,7 +117,7 @@ From Dokku versions `0.5.0` until `0.11.0`, enabling or disabling an application
Custom plugins names _must_ have the suffix `-vhosts` or scheduler overriding via `proxy:set` may not function as expected.
-At this time, the following dokku commands are used to implement a complete proxy implementation.
+At this time, the following dokku commands are used to interact with a complete proxy implementation.
- `domains:add`: Adds a given domain to an app.
- triggers: `post-domains-update`
@@ -158,13 +139,13 @@ At this time, the following dokku commands are used to implement a complete prox
- triggers: `proxy-disable`
- `proxy:enable`: Enables the proxy configuration for an app.
- triggers: `proxy-enable`
-- `proxy:ports-add`: Adds one or more port mappings to an app
+- `ports:add`: Adds one or more port mappings to an app
- triggers: `post-proxy-ports-update`
-- `proxy:ports-clear`: Clears out all port mappings for an app.
+- `ports:clear`: Clears out all port mappings for an app.
- triggers: `post-proxy-ports-update`
-- `proxy:ports-remove`: Removes one or more port mappings from an app.
+- `ports:remove`: Removes one or more port mappings from an app.
- triggers: `post-proxy-ports-update`
-- `proxy:ports-set`: Sets all port mappings for an app.
+- `ports:set`: Sets all port mappings for an app.
- triggers: `post-proxy-ports-update`
Proxy implementations may decide to omit some functionality here, or use plugin triggers to supplement config with information from other plugins.
diff --git a/plugins/ports/.gitignore b/plugins/ports/.gitignore
new file mode 100644
index 00000000000..291036bd409
--- /dev/null
+++ b/plugins/ports/.gitignore
@@ -0,0 +1,7 @@
+/commands
+/subcommands/*
+/triggers/*
+/triggers
+/install
+/post-*
+/report
diff --git a/plugins/ports/Makefile b/plugins/ports/Makefile
new file mode 100644
index 00000000000..2149ff8543e
--- /dev/null
+++ b/plugins/ports/Makefile
@@ -0,0 +1,6 @@
+SUBCOMMANDS = subcommands/list subcommands/add subcommands/clear subcommands/remove subcommands/set subcommands/report
+TRIGGERS = triggers/post-certs-remove triggers/post-certs-update triggers/report
+BUILD = commands subcommands triggers
+PLUGIN_NAME = ports
+
+include ../../common.mk
diff --git a/plugins/ports/functions.go b/plugins/ports/functions.go
new file mode 100644
index 00000000000..06fdc164115
--- /dev/null
+++ b/plugins/ports/functions.go
@@ -0,0 +1,188 @@
+package ports
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+
+ "github.com/dokku/dokku/plugins/common"
+ "github.com/dokku/dokku/plugins/config"
+ "github.com/ryanuber/columnize"
+)
+
+func addPortMaps(appName string, portMaps []PortMap) error {
+ allPortMaps := getPortMaps(appName)
+ allPortMaps = append(allPortMaps, portMaps...)
+
+ return setPortMaps(appName, allPortMaps)
+}
+
+func filterAppPortMaps(appName string, scheme string, hostPort int) []PortMap {
+ var filteredPortMaps []PortMap
+ for _, portMap := range getPortMaps(appName) {
+ if portMap.Scheme == scheme && portMap.HostPort == hostPort {
+ filteredPortMaps = append(filteredPortMaps, portMap)
+ }
+ }
+
+ return filteredPortMaps
+}
+
+func getPortMaps(appName string) []PortMap {
+ value := config.GetWithDefault(appName, "DOKKU_PROXY_PORT_MAP", "")
+ portMaps, _ := parsePortMapString(value)
+ return portMaps
+}
+
+func inRange(value int, min int, max int) bool {
+ return min < value && value < max
+}
+
+func listAppPortMaps(appName string) error {
+ portMaps := getPortMaps(appName)
+
+ if len(portMaps) == 0 {
+ return errors.New("No port mappings configured for app")
+ }
+
+ var lines []string
+ if os.Getenv("DOKKU_QUIET_OUTPUT") == "" {
+ lines = append(lines, "-----> scheme:host port:container port")
+ }
+
+ for _, portMap := range portMaps {
+ lines = append(lines, portMap.String())
+ }
+
+ sort.Strings(lines)
+ common.LogInfo1Quiet(fmt.Sprintf("Port mappings for %s", appName))
+ config := columnize.DefaultConfig()
+ config.Delim = ":"
+ config.Prefix = " "
+ config.Empty = ""
+ fmt.Println(columnize.Format(lines, config))
+ return nil
+}
+
+func parsePortMapString(stringPortMap string) ([]PortMap, error) {
+ var portMaps []PortMap
+
+ for _, v := range strings.Split(strings.TrimSpace(stringPortMap), " ") {
+ parts := strings.SplitN(v, ":", 3)
+ if len(parts) == 1 {
+ hostPort, err := strconv.Atoi(v)
+ if err != nil {
+ return portMaps, fmt.Errorf("Invalid port map %s [err=%s]", v, err.Error())
+ }
+
+ if !inRange(hostPort, 0, 65536) {
+ return portMaps, fmt.Errorf("Invalid port map %s [hostPort=%d]", v, hostPort)
+ }
+
+ portMaps = append(portMaps, PortMap{
+ HostPort: hostPort,
+ Scheme: "__internal__",
+ })
+ continue
+ }
+
+ if len(parts) != 3 {
+ return portMaps, fmt.Errorf("Invalid port map %s [len=%d]", v, len(parts))
+ }
+
+ hostPort, err := strconv.Atoi(parts[1])
+ if err != nil {
+ return portMaps, fmt.Errorf("Invalid port map %s [err=%s]", v, err.Error())
+ }
+
+ containerPort, err := strconv.Atoi(parts[2])
+ if err != nil {
+ return portMaps, fmt.Errorf("Invalid port map %s [err=%s]", v, err.Error())
+ }
+
+ if !inRange(hostPort, 0, 65536) {
+ return portMaps, fmt.Errorf("Invalid port map %s [hostPort=%d]", v, hostPort)
+ }
+
+ if !inRange(containerPort, 0, 65536) {
+ return portMaps, fmt.Errorf("Invalid port map %s [containerPort=%d]", v, containerPort)
+ }
+
+ portMaps = append(portMaps, PortMap{
+ ContainerPort: containerPort,
+ HostPort: hostPort,
+ Scheme: parts[0],
+ })
+ }
+
+ return uniquePortMaps(portMaps), nil
+}
+
+func removePortMaps(appName string, portMaps []PortMap) error {
+ toRemove := map[string]bool{}
+ toRemoveByPort := map[int]bool{}
+
+ for _, portMap := range portMaps {
+ if portMap.AllowsPersistence() {
+ toRemoveByPort[portMap.HostPort] = true
+ continue
+ }
+ toRemove[portMap.String()] = true
+ }
+
+ var toSet []PortMap
+ for _, portMap := range getPortMaps(appName) {
+ if toRemove[portMap.String()] {
+ continue
+ }
+
+ if toRemoveByPort[portMap.HostPort] {
+ continue
+ }
+
+ toSet = append(toSet, portMap)
+ }
+
+ if len(toSet) == 0 {
+ keys := []string{"DOKKU_PROXY_PORT_MAP"}
+ return config.UnsetMany(appName, keys, false)
+ }
+
+ return setPortMaps(appName, toSet)
+}
+
+func setPortMaps(appName string, portMaps []PortMap) error {
+ var value []string
+ for _, portMap := range uniquePortMaps(portMaps) {
+ if portMap.AllowsPersistence() {
+ continue
+ }
+
+ value = append(value, portMap.String())
+ }
+
+ sort.Strings(value)
+ entries := map[string]string{
+ "DOKKU_PROXY_PORT_MAP": strings.Join(value, " "),
+ }
+ return config.SetMany(appName, entries, false)
+}
+
+func uniquePortMaps(portMaps []PortMap) []PortMap {
+ var unique []PortMap
+ existingPortMaps := map[string]bool{}
+
+ for _, portMap := range portMaps {
+ if existingPortMaps[portMap.String()] {
+ continue
+ }
+
+ existingPortMaps[portMap.String()] = true
+ unique = append(unique, portMap)
+ }
+
+ return unique
+}
diff --git a/plugins/ports/go.mod b/plugins/ports/go.mod
new file mode 100644
index 00000000000..2ab83576b63
--- /dev/null
+++ b/plugins/ports/go.mod
@@ -0,0 +1,23 @@
+module github.com/dokku/dokku/plugins/ports
+
+go 1.19
+
+require (
+ github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
+ github.com/dokku/dokku/plugins/config v0.0.0-00010101000000-000000000000
+ github.com/ryanuber/columnize v2.1.2+incompatible
+ github.com/spf13/pflag v1.0.5
+)
+
+require (
+ github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
+ github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
+ github.com/joho/godotenv v1.2.0 // indirect
+ github.com/otiai10/copy v1.12.0 // indirect
+ golang.org/x/sync v0.3.0 // indirect
+ golang.org/x/sys v0.8.0 // indirect
+)
+
+replace github.com/dokku/dokku/plugins/common => ../common
+
+replace github.com/dokku/dokku/plugins/config => ../config
diff --git a/plugins/ports/go.sum b/plugins/ports/go.sum
new file mode 100644
index 00000000000..1a7ae7db219
--- /dev/null
+++ b/plugins/ports/go.sum
@@ -0,0 +1,22 @@
+github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
+github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
+github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
+github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/joho/godotenv v1.2.0 h1:vGTvz69FzUFp+X4/bAkb0j5BoLC+9bpqTWY8mjhA9pc=
+github.com/joho/godotenv v1.2.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
+github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
+github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY=
+github.com/otiai10/copy v1.12.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww=
+github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
+github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF25UfsK2X7Ph/zCAk=
+github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
+golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/plugins/ports/plugin.toml b/plugins/ports/plugin.toml
new file mode 100644
index 00000000000..a43ba8fb502
--- /dev/null
+++ b/plugins/ports/plugin.toml
@@ -0,0 +1,4 @@
+[plugin]
+description = "dokku core ports plugin"
+version = "0.30.8"
+[plugin.config]
diff --git a/plugins/proxy/proxy-configure-ports b/plugins/ports/proxy-configure-ports
similarity index 90%
rename from plugins/proxy/proxy-configure-ports
rename to plugins/ports/proxy-configure-ports
index 21c94a69e3b..deee9b39da9 100755
--- a/plugins/proxy/proxy-configure-ports
+++ b/plugins/ports/proxy-configure-ports
@@ -4,8 +4,8 @@ source "$PLUGIN_AVAILABLE_PATH/config/functions"
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
-trigger-proxy-proxy-configure-ports() {
- declare desc="proxy proxy-configure-ports plugin trigger"
+trigger-ports-proxy-configure-ports() {
+ declare desc="ports proxy-configure-ports plugin trigger"
declare trigger="proxy-configure-ports"
declare APP="$1"
local RAW_TCP_PORTS="$(get_app_raw_tcp_ports "$APP")"
@@ -19,7 +19,7 @@ trigger-proxy-proxy-configure-ports() {
if [[ -z "$DOKKU_PROXY_PORT" ]] && [[ -z "$RAW_TCP_PORTS" ]]; then
if [[ "$IS_APP_VHOST_ENABLED" == "false" ]]; then
- dokku_log_info1 "No proxy port set, setting to random open high port"
+ dokku_log_info1 "No port set, setting to random open high port"
local PROXY_PORT=$(get_available_port)
else
local PROXY_PORT=$(config_get --global DOKKU_PROXY_PORT)
@@ -32,7 +32,7 @@ trigger-proxy-proxy-configure-ports() {
local PROXY_SSL_PORT=$(config_get --global DOKKU_PROXY_SSL_PORT)
PROXY_SSL_PORT=${PROXY_SSL_PORT:=443}
if [[ -z "$RAW_TCP_PORTS" ]] && [[ "$IS_APP_VHOST_ENABLED" == "false" ]]; then
- dokku_log_info1 "No proxy ssl port set, setting to random open high port"
+ dokku_log_info1 "No ssl port set, setting to random open high port"
PROXY_SSL_PORT=$(get_available_port)
fi
DOKKU_QUIET_OUTPUT=1 config_set --no-restart "$APP" DOKKU_PROXY_SSL_PORT="$PROXY_SSL_PORT"
@@ -61,4 +61,5 @@ trigger-proxy-proxy-configure-ports() {
fi
fi
}
-trigger-proxy-proxy-configure-ports "$@"
+
+trigger-ports-proxy-configure-ports "$@"
diff --git a/plugins/ports/proxy.go b/plugins/ports/proxy.go
new file mode 100644
index 00000000000..1918a8c531b
--- /dev/null
+++ b/plugins/ports/proxy.go
@@ -0,0 +1,21 @@
+package ports
+
+import (
+ "fmt"
+)
+
+// PortMap is a struct that contains a scheme:host-port:container-port mapping
+type PortMap struct {
+ ContainerPort int
+ HostPort int
+ Scheme string
+}
+
+func (p PortMap) String() string {
+ return fmt.Sprintf("%s:%d:%d", p.Scheme, p.HostPort, p.ContainerPort)
+}
+
+// AllowsPersistence returns true if the port map is not to be persisted
+func (p PortMap) AllowsPersistence() bool {
+ return p.Scheme == "__internal__"
+}
diff --git a/plugins/ports/report.go b/plugins/ports/report.go
new file mode 100644
index 00000000000..bd820554da2
--- /dev/null
+++ b/plugins/ports/report.go
@@ -0,0 +1,37 @@
+package ports
+
+import (
+ "strings"
+
+ "github.com/dokku/dokku/plugins/common"
+)
+
+// ReportSingleApp is an internal function that displays the ports report for one or more apps
+func ReportSingleApp(appName string, format string, infoFlag string) error {
+ if err := common.VerifyAppName(appName); err != nil {
+ return err
+ }
+
+ flags := map[string]common.ReportFunc{
+ "--ports-map": reportPortMap,
+ }
+
+ flagKeys := []string{}
+ for flagKey := range flags {
+ flagKeys = append(flagKeys, flagKey)
+ }
+
+ trimPrefix := false
+ uppercaseFirstCharacter := true
+ infoFlags := common.CollectReport(appName, infoFlag, flags)
+ return common.ReportSingleApp("ports", appName, infoFlag, infoFlags, flagKeys, format, trimPrefix, uppercaseFirstCharacter)
+}
+
+func reportPortMap(appName string) string {
+ var portMaps []string
+ for _, portMap := range getPortMaps(appName) {
+ portMaps = append(portMaps, portMap.String())
+ }
+
+ return strings.Join(portMaps, " ")
+}
diff --git a/plugins/ports/src/commands/commands.go b/plugins/ports/src/commands/commands.go
new file mode 100644
index 00000000000..9231d27bf29
--- /dev/null
+++ b/plugins/ports/src/commands/commands.go
@@ -0,0 +1,60 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+
+ "github.com/dokku/dokku/plugins/common"
+)
+
+const (
+ helpHeader = `Usage: dokku ports[:COMMAND]
+
+Manage ports for an app
+
+Additional commands:`
+
+ helpContent = `
+ ports:list , List port mappings for app
+ ports:add [::...], Add port mappings to an app
+ ports:clear , Clear all port mappings for an app
+ ports:remove [|::...], Remove specific port mappings from an app
+ ports:set [::...], Set port mappings for an app
+ ports:report [] [], Displays a ports report for one or more apps
+`
+)
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+
+ cmd := flag.Arg(0)
+ switch cmd {
+ case "ports", "ports:help":
+ usage()
+ case "help":
+ command := common.NewShellCmd(fmt.Sprintf("ps -o command= %d", os.Getppid()))
+ command.ShowOutput = false
+ output, err := command.Output()
+
+ if err == nil && strings.Contains(string(output), "--all") {
+ fmt.Println(helpContent)
+ } else {
+ fmt.Print("\n ports, Manage ports for an app\n")
+ }
+ default:
+ dokkuNotImplementExitCode, err := strconv.Atoi(os.Getenv("DOKKU_NOT_IMPLEMENTED_EXIT"))
+ if err != nil {
+ fmt.Println("failed to retrieve DOKKU_NOT_IMPLEMENTED_EXIT environment variable")
+ dokkuNotImplementExitCode = 10
+ }
+ os.Exit(dokkuNotImplementExitCode)
+ }
+}
+
+func usage() {
+ common.CommandUsage(helpHeader, helpContent)
+}
diff --git a/plugins/ports/src/subcommands/subcommands.go b/plugins/ports/src/subcommands/subcommands.go
new file mode 100644
index 00000000000..14f97ed9418
--- /dev/null
+++ b/plugins/ports/src/subcommands/subcommands.go
@@ -0,0 +1,65 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/dokku/dokku/plugins/common"
+ "github.com/dokku/dokku/plugins/ports"
+
+ flag "github.com/spf13/pflag"
+)
+
+// main entrypoint to all subcommands
+func main() {
+ parts := strings.Split(os.Args[0], "/")
+ subcommand := parts[len(parts)-1]
+
+ var err error
+ switch subcommand {
+ case "list":
+ args := flag.NewFlagSet("ports:list", flag.ExitOnError)
+ args.Parse(os.Args[2:])
+ appName := args.Arg(0)
+ err = ports.CommandList(appName)
+ case "add":
+ args := flag.NewFlagSet("ports:add", flag.ExitOnError)
+ args.Parse(os.Args[2:])
+ appName := args.Arg(0)
+ _, portMaps := common.ShiftString(args.Args())
+ err = ports.CommandAdd(appName, portMaps)
+ case "clear":
+ args := flag.NewFlagSet("ports:clear", flag.ExitOnError)
+ args.Parse(os.Args[2:])
+ appName := args.Arg(0)
+ err = ports.CommandClear(appName)
+ case "remove":
+ args := flag.NewFlagSet("ports:remove", flag.ExitOnError)
+ args.Parse(os.Args[2:])
+ appName := args.Arg(0)
+ _, portMaps := common.ShiftString(args.Args())
+ err = ports.CommandRemove(appName, portMaps)
+ case "set":
+ args := flag.NewFlagSet("ports:set", flag.ExitOnError)
+ args.Parse(os.Args[2:])
+ appName := args.Arg(0)
+ _, portMaps := common.ShiftString(args.Args())
+ err = ports.CommandSet(appName, portMaps)
+ case "report":
+ args := flag.NewFlagSet("ports:report", flag.ExitOnError)
+ format := args.String("format", "stdout", "format: [ stdout | json ]")
+ osArgs, infoFlag, flagErr := common.ParseReportArgs("ports", os.Args[2:])
+ if flagErr == nil {
+ args.Parse(osArgs)
+ appName := args.Arg(0)
+ err = ports.CommandReport(appName, *format, infoFlag)
+ }
+ default:
+ err = fmt.Errorf("Invalid plugin subcommand call: %s", subcommand)
+ }
+
+ if err != nil {
+ common.LogFailWithError(err)
+ }
+}
diff --git a/plugins/ports/src/triggers/triggers.go b/plugins/ports/src/triggers/triggers.go
new file mode 100644
index 00000000000..f159dbf57d2
--- /dev/null
+++ b/plugins/ports/src/triggers/triggers.go
@@ -0,0 +1,37 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/dokku/dokku/plugins/common"
+ "github.com/dokku/dokku/plugins/ports"
+)
+
+// main entrypoint to all triggers
+func main() {
+ parts := strings.Split(os.Args[0], "/")
+ trigger := parts[len(parts)-1]
+ flag.Parse()
+
+ var err error
+ switch trigger {
+ 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 "report":
+ appName := flag.Arg(0)
+ err = ports.ReportSingleApp(appName, "", "")
+ default:
+ err = fmt.Errorf("Invalid plugin trigger call: %s", trigger)
+ }
+
+ if err != nil {
+ common.LogFailWithError(err)
+ }
+}
diff --git a/plugins/ports/subcommands.go b/plugins/ports/subcommands.go
new file mode 100644
index 00000000000..70ebf905746
--- /dev/null
+++ b/plugins/ports/subcommands.go
@@ -0,0 +1,116 @@
+package ports
+
+import (
+ "errors"
+ "strings"
+
+ "github.com/dokku/dokku/plugins/common"
+ "github.com/dokku/dokku/plugins/config"
+)
+
+// CommandList is a cmd wrapper to list port mappings for an app
+func CommandList(appName string) error {
+ if err := common.VerifyAppName(appName); err != nil {
+ return err
+ }
+
+ return listAppPortMaps(appName)
+}
+
+// CommandAdd adds port mappings to an app
+func CommandAdd(appName string, portMapStrings []string) error {
+ if err := common.VerifyAppName(appName); err != nil {
+ return err
+ }
+
+ if len(portMapStrings) == 0 {
+ return errors.New("No port mapping specified")
+ }
+
+ portMaps, err := parsePortMapString(strings.Join(portMapStrings, " "))
+ if err != nil {
+ return err
+ }
+
+ if err := addPortMaps(appName, portMaps); err != nil {
+ return err
+ }
+
+ return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "add"}...)
+}
+
+// CommandClear clears all port mappings for an app
+func CommandClear(appName string) error {
+ if err := common.VerifyAppName(appName); err != nil {
+ return err
+ }
+
+ keys := []string{"DOKKU_PROXY_PORT_MAP"}
+ if err := config.UnsetMany(appName, keys, false); err != nil {
+ return err
+ }
+
+ return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "clear"}...)
+}
+
+// CommandRemove removes specific port mappings from an app
+func CommandRemove(appName string, portMapStrings []string) error {
+ if err := common.VerifyAppName(appName); err != nil {
+ return err
+ }
+
+ if len(portMapStrings) == 0 {
+ return errors.New("No port mapping specified")
+ }
+
+ portMaps, err := parsePortMapString(strings.Join(portMapStrings, " "))
+ if err != nil {
+ return err
+ }
+
+ if err := removePortMaps(appName, portMaps); err != nil {
+ return err
+ }
+
+ return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "remove"}...)
+}
+
+// CommandSet sets port mappings for an app
+func CommandSet(appName string, portMapStrings []string) error {
+ if err := common.VerifyAppName(appName); err != nil {
+ return err
+ }
+
+ if len(portMapStrings) == 0 {
+ return errors.New("No port mapping specified")
+ }
+
+ portMaps, err := parsePortMapString(strings.Join(portMapStrings, " "))
+ if err != nil {
+ return err
+ }
+
+ if err := setPortMaps(appName, portMaps); err != nil {
+ return err
+ }
+
+ return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "set"}...)
+}
+
+// CommandReport displays a ports report for one or more apps
+func CommandReport(appName string, format string, infoFlag string) error {
+ if len(appName) == 0 {
+ apps, err := common.DokkuApps()
+ if err != nil {
+ return err
+ }
+ for _, appName := range apps {
+ if err := ReportSingleApp(appName, format, infoFlag); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ return ReportSingleApp(appName, format, infoFlag)
+}
diff --git a/plugins/ports/triggers.go b/plugins/ports/triggers.go
new file mode 100644
index 00000000000..aa209200a7b
--- /dev/null
+++ b/plugins/ports/triggers.go
@@ -0,0 +1,71 @@
+package ports
+
+import (
+ "github.com/dokku/dokku/plugins/config"
+)
+
+// TriggerPostCertsRemove unsets port config vars after SSL cert is added
+func TriggerPostCertsRemove(appName string) error {
+ keys := []string{"DOKKU_PROXY_SSL_PORT"}
+ if err := config.UnsetMany(appName, keys, false); err != nil {
+ return err
+ }
+
+ return removePortMaps(appName, filterAppPortMaps(appName, "https", 443))
+}
+
+// TriggerPostCertsUpdate sets port config vars after SSL cert is added
+func TriggerPostCertsUpdate(appName string) error {
+ port := config.GetWithDefault(appName, "DOKKU_PROXY_PORT", "")
+ sslPort := config.GetWithDefault(appName, "DOKKU_PROXY_SSL_PORT", "")
+ portMaps := getPortMaps(appName)
+
+ toUnset := []string{}
+ if port == "80" {
+ toUnset = append(toUnset, "DOKKU_PROXY_PORT")
+ }
+ if sslPort == "443" {
+ toUnset = append(toUnset, "DOKKU_PROXY_SSL_PORT")
+ }
+
+ if len(toUnset) > 0 {
+ if err := config.UnsetMany(appName, toUnset, false); err != nil {
+ return err
+ }
+ }
+
+ var http80Ports []PortMap
+ for _, portMap := range portMaps {
+ if portMap.Scheme == "http" && portMap.HostPort == 80 {
+ http80Ports = append(http80Ports, portMap)
+ }
+ }
+
+ if len(http80Ports) > 0 {
+ var https443Ports []PortMap
+ for _, portMap := range portMaps {
+ if portMap.Scheme == "https" && portMap.HostPort == 443 {
+ https443Ports = append(https443Ports, portMap)
+ }
+ }
+
+ if err := removePortMaps(appName, https443Ports); err != nil {
+ return err
+ }
+
+ var toAdd []PortMap
+ for _, portMap := range http80Ports {
+ toAdd = append(toAdd, PortMap{
+ Scheme: "https",
+ HostPort: 443,
+ ContainerPort: portMap.ContainerPort,
+ })
+ }
+
+ if err := addPortMaps(appName, toAdd); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/plugins/proxy/.gitignore b/plugins/proxy/.gitignore
index 3b20f2e1cfc..7d9f06e65fe 100644
--- a/plugins/proxy/.gitignore
+++ b/plugins/proxy/.gitignore
@@ -6,4 +6,4 @@
/install
/post-*
/report
-!/proxy-configure-ports
+
diff --git a/plugins/proxy/Makefile b/plugins/proxy/Makefile
index 21cc25c91fd..6b127937fe9 100644
--- a/plugins/proxy/Makefile
+++ b/plugins/proxy/Makefile
@@ -1,5 +1,5 @@
SUBCOMMANDS = subcommands/build-config subcommands/clear-config subcommands/disable subcommands/enable subcommands/ports subcommands/ports-add subcommands/ports-clear subcommands/ports-remove subcommands/ports-set subcommands/report subcommands/set
-TRIGGERS = triggers/proxy-is-enabled triggers/proxy-type triggers/post-certs-remove triggers/post-certs-update triggers/report
+TRIGGERS = triggers/proxy-is-enabled triggers/proxy-type triggers/report
BUILD = commands subcommands triggers
PLUGIN_NAME = proxy
diff --git a/plugins/proxy/functions.go b/plugins/proxy/functions.go
index bc12f32a9e6..4b5467f50e3 100644
--- a/plugins/proxy/functions.go
+++ b/plugins/proxy/functions.go
@@ -1,192 +1,9 @@
package proxy
import (
- "errors"
- "fmt"
- "os"
- "sort"
- "strconv"
- "strings"
-
- "github.com/dokku/dokku/plugins/common"
"github.com/dokku/dokku/plugins/config"
- "github.com/ryanuber/columnize"
)
-func addProxyPorts(appName string, proxyPortMap []PortMap) error {
- allPortMaps := getProxyPortMap(appName)
- allPortMaps = append(allPortMaps, proxyPortMap...)
-
- return setProxyPorts(appName, allPortMaps)
-}
-
-func filterAppProxyPorts(appName string, scheme string, hostPort int) []PortMap {
- var filteredProxyMaps []PortMap
- for _, portMap := range getProxyPortMap(appName) {
- if portMap.Scheme == scheme && portMap.HostPort == hostPort {
- filteredProxyMaps = append(filteredProxyMaps, portMap)
- }
- }
-
- return filteredProxyMaps
-}
-
func getAppProxyType(appName string) string {
return config.GetWithDefault(appName, "DOKKU_APP_PROXY_TYPE", "nginx")
}
-
-func getProxyPortMap(appName string) []PortMap {
- value := config.GetWithDefault(appName, "DOKKU_PROXY_PORT_MAP", "")
- portMaps, _ := parseProxyPortMapString(value)
- return portMaps
-}
-
-func inRange(value int, min int, max int) bool {
- return min < value && value < max
-}
-
-func listAppProxyPorts(appName string) error {
- proxyPortMap := getProxyPortMap(appName)
-
- if len(proxyPortMap) == 0 {
- return errors.New("No port mappings configured for app")
- }
-
- var lines []string
- if os.Getenv("DOKKU_QUIET_OUTPUT") == "" {
- lines = append(lines, "-----> scheme:host port:container port")
- }
-
- for _, portMap := range proxyPortMap {
- lines = append(lines, portMap.String())
- }
-
- sort.Strings(lines)
- common.LogInfo1Quiet(fmt.Sprintf("Port mappings for %s", appName))
- config := columnize.DefaultConfig()
- config.Delim = ":"
- config.Prefix = " "
- config.Empty = ""
- fmt.Println(columnize.Format(lines, config))
- return nil
-}
-
-func parseProxyPortMapString(stringPortMap string) ([]PortMap, error) {
- var proxyPortMap []PortMap
-
- for _, v := range strings.Split(strings.TrimSpace(stringPortMap), " ") {
- parts := strings.SplitN(v, ":", 3)
- if len(parts) == 1 {
- hostPort, err := strconv.Atoi(v)
- if err != nil {
- return proxyPortMap, fmt.Errorf("Invalid port map %s [err=%s]", v, err.Error())
- }
-
- if !inRange(hostPort, 0, 65536) {
- return proxyPortMap, fmt.Errorf("Invalid port map %s [hostPort=%d]", v, hostPort)
- }
-
- proxyPortMap = append(proxyPortMap, PortMap{
- HostPort: hostPort,
- Scheme: "__internal__",
- })
- continue
- }
-
- if len(parts) != 3 {
- return proxyPortMap, fmt.Errorf("Invalid port map %s [len=%d]", v, len(parts))
- }
-
- hostPort, err := strconv.Atoi(parts[1])
- if err != nil {
- return proxyPortMap, fmt.Errorf("Invalid port map %s [err=%s]", v, err.Error())
- }
-
- containerPort, err := strconv.Atoi(parts[2])
- if err != nil {
- return proxyPortMap, fmt.Errorf("Invalid port map %s [err=%s]", v, err.Error())
- }
-
- if !inRange(hostPort, 0, 65536) {
- return proxyPortMap, fmt.Errorf("Invalid port map %s [hostPort=%d]", v, hostPort)
- }
-
- if !inRange(containerPort, 0, 65536) {
- return proxyPortMap, fmt.Errorf("Invalid port map %s [containerPort=%d]", v, containerPort)
- }
-
- proxyPortMap = append(proxyPortMap, PortMap{
- ContainerPort: containerPort,
- HostPort: hostPort,
- Scheme: parts[0],
- })
- }
-
- return uniqueProxyPortMap(proxyPortMap), nil
-}
-
-func removeProxyPorts(appName string, proxyPortMap []PortMap) error {
- toRemove := map[string]bool{}
- toRemoveByPort := map[int]bool{}
-
- for _, portMap := range proxyPortMap {
- if portMap.AllowsPersistence() {
- toRemoveByPort[portMap.HostPort] = true
- continue
- }
- toRemove[portMap.String()] = true
- }
-
- var toSet []PortMap
- for _, portMap := range getProxyPortMap(appName) {
- if toRemove[portMap.String()] {
- continue
- }
-
- if toRemoveByPort[portMap.HostPort] {
- continue
- }
-
- toSet = append(toSet, portMap)
- }
-
- if len(toSet) == 0 {
- keys := []string{"DOKKU_PROXY_PORT_MAP"}
- return config.UnsetMany(appName, keys, false)
- }
-
- return setProxyPorts(appName, toSet)
-}
-
-func setProxyPorts(appName string, proxyPortMap []PortMap) error {
- var value []string
- for _, portMap := range uniqueProxyPortMap(proxyPortMap) {
- if portMap.AllowsPersistence() {
- continue
- }
-
- value = append(value, portMap.String())
- }
-
- sort.Strings(value)
- entries := map[string]string{
- "DOKKU_PROXY_PORT_MAP": strings.Join(value, " "),
- }
- return config.SetMany(appName, entries, false)
-}
-
-func uniqueProxyPortMap(proxyPortMap []PortMap) []PortMap {
- var unique []PortMap
- existingPortMaps := map[string]bool{}
-
- for _, portMap := range proxyPortMap {
- if existingPortMaps[portMap.String()] {
- continue
- }
-
- existingPortMaps[portMap.String()] = true
- unique = append(unique, portMap)
- }
-
- return unique
-}
diff --git a/plugins/proxy/go.mod b/plugins/proxy/go.mod
index 7f9fe76ea43..3590d645a21 100644
--- a/plugins/proxy/go.mod
+++ b/plugins/proxy/go.mod
@@ -5,7 +5,7 @@ go 1.19
require (
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
github.com/dokku/dokku/plugins/config v0.0.0-00010101000000-000000000000
- github.com/ryanuber/columnize v2.1.2+incompatible
+ github.com/dokku/dokku/plugins/ports v0.0.0-00010101000000-000000000000
github.com/spf13/pflag v1.0.5
)
@@ -14,6 +14,7 @@ require (
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
github.com/joho/godotenv v1.2.0 // indirect
github.com/otiai10/copy v1.12.0 // indirect
+ github.com/ryanuber/columnize v2.1.2+incompatible // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.8.0 // indirect
)
@@ -21,3 +22,5 @@ require (
replace github.com/dokku/dokku/plugins/common => ../common
replace github.com/dokku/dokku/plugins/config => ../config
+
+replace github.com/dokku/dokku/plugins/ports => ../ports
diff --git a/plugins/proxy/proxy.go b/plugins/proxy/proxy.go
index ec87bf48c5e..26cfee2ffb4 100644
--- a/plugins/proxy/proxy.go
+++ b/plugins/proxy/proxy.go
@@ -1,8 +1,6 @@
package proxy
import (
- "fmt"
-
"github.com/dokku/dokku/plugins/common"
"github.com/dokku/dokku/plugins/config"
)
@@ -11,22 +9,6 @@ import (
// and defaults to -1 (false)
const RunInSerial = 0
-// PortMap is a struct that contains a scheme:host-port:container-port mapping
-type PortMap struct {
- ContainerPort int
- HostPort int
- Scheme string
-}
-
-func (p PortMap) String() string {
- return fmt.Sprintf("%s:%d:%d", p.Scheme, p.HostPort, p.ContainerPort)
-}
-
-// AllowsPersistence returns true if the port map is not to be persisted
-func (p PortMap) AllowsPersistence() bool {
- return p.Scheme == "__internal__"
-}
-
// BuildConfig rebuilds the proxy config for the specified app
func BuildConfig(appName string) error {
return common.PlugnTrigger("proxy-build-config", []string{appName}...)
diff --git a/plugins/proxy/report.go b/plugins/proxy/report.go
index bf4c5c917b4..5db7792a2f6 100644
--- a/plugins/proxy/report.go
+++ b/plugins/proxy/report.go
@@ -1,8 +1,6 @@
package proxy
import (
- "strings"
-
"github.com/dokku/dokku/plugins/common"
)
@@ -13,9 +11,8 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
}
flags := map[string]common.ReportFunc{
- "--proxy-enabled": reportEnabled,
- "--proxy-type": reportType,
- "--proxy-port-map": reportPortMap,
+ "--proxy-enabled": reportEnabled,
+ "--proxy-type": reportType,
}
flagKeys := []string{}
@@ -41,12 +38,3 @@ func reportEnabled(appName string) string {
func reportType(appName string) string {
return getAppProxyType(appName)
}
-
-func reportPortMap(appName string) string {
- var proxyPortMap []string
- for _, portMap := range getProxyPortMap(appName) {
- proxyPortMap = append(proxyPortMap, portMap.String())
- }
-
- return strings.Join(proxyPortMap, " ")
-}
diff --git a/plugins/proxy/src/commands/commands.go b/plugins/proxy/src/commands/commands.go
index e2f6c016a81..129cc282082 100644
--- a/plugins/proxy/src/commands/commands.go
+++ b/plugins/proxy/src/commands/commands.go
@@ -22,11 +22,6 @@ Additional commands:`
proxy:clear-config [--all|], Clears config for a given app
proxy:disable , Disable proxy for app
proxy:enable , Enable proxy for app
- proxy:ports , List proxy port mappings for app
- proxy:ports-add [::...], Add proxy port mappings to an app
- proxy:ports-clear , Clear all proxy port mappings for an app
- proxy:ports-remove [|::...], Remove specific proxy port mappings from an app
- proxy:ports-set [::...], Set proxy port mappings for an app
proxy:report [] [], Displays a proxy report for one or more apps
proxy:set , Set proxy type for app
`
diff --git a/plugins/proxy/src/subcommands/subcommands.go b/plugins/proxy/src/subcommands/subcommands.go
index c25db395ccb..0dd97285765 100644
--- a/plugins/proxy/src/subcommands/subcommands.go
+++ b/plugins/proxy/src/subcommands/subcommands.go
@@ -6,6 +6,7 @@ import (
"strings"
"github.com/dokku/dokku/plugins/common"
+ "github.com/dokku/dokku/plugins/ports"
"github.com/dokku/dokku/plugins/proxy"
flag "github.com/spf13/pflag"
@@ -49,30 +50,35 @@ func main() {
args := flag.NewFlagSet("proxy:ports", flag.ExitOnError)
args.Parse(os.Args[2:])
appName := args.Arg(0)
- err = proxy.CommandPorts(appName)
+ common.LogWarn("Deprecated: Use 'ports:list' instead")
+ err = ports.CommandList(appName)
case "ports-add":
args := flag.NewFlagSet("proxy:ports-add", flag.ExitOnError)
args.Parse(os.Args[2:])
appName := args.Arg(0)
_, portMaps := common.ShiftString(args.Args())
- err = proxy.CommandPortsAdd(appName, portMaps)
+ common.LogWarn("Deprecated: Use 'ports:add' instead")
+ err = ports.CommandAdd(appName, portMaps)
case "ports-clear":
args := flag.NewFlagSet("proxy:ports-clear", flag.ExitOnError)
args.Parse(os.Args[2:])
appName := args.Arg(0)
- err = proxy.CommandPortsClear(appName)
+ common.LogWarn("Deprecated: Use 'ports:clear' instead")
+ err = ports.CommandClear(appName)
case "ports-remove":
args := flag.NewFlagSet("proxy:ports-remove", flag.ExitOnError)
args.Parse(os.Args[2:])
appName := args.Arg(0)
_, portMaps := common.ShiftString(args.Args())
- err = proxy.CommandPortsRemove(appName, portMaps)
+ common.LogWarn("Deprecated: Use 'ports:remove' instead")
+ err = ports.CommandRemove(appName, portMaps)
case "ports-set":
args := flag.NewFlagSet("proxy:ports-set", flag.ExitOnError)
args.Parse(os.Args[2:])
appName := args.Arg(0)
_, portMaps := common.ShiftString(args.Args())
- err = proxy.CommandPortsSet(appName, portMaps)
+ common.LogWarn("Deprecated: Use 'ports:set' instead")
+ err = ports.CommandSet(appName, portMaps)
case "report":
args := flag.NewFlagSet("proxy:report", flag.ExitOnError)
format := args.String("format", "stdout", "format: [ stdout | json ]")
diff --git a/plugins/proxy/src/triggers/triggers.go b/plugins/proxy/src/triggers/triggers.go
index 11c5bd277ab..713e1976d0c 100644
--- a/plugins/proxy/src/triggers/triggers.go
+++ b/plugins/proxy/src/triggers/triggers.go
@@ -24,12 +24,6 @@ func main() {
case "proxy-type":
appName := flag.Arg(0)
err = proxy.TriggerProxyType(appName)
- case "post-certs-remove":
- appName := flag.Arg(0)
- err = proxy.TriggerPostCertsRemove(appName)
- case "post-certs-update":
- appName := flag.Arg(0)
- err = proxy.TriggerPostCertsUpdate(appName)
case "report":
appName := flag.Arg(0)
err = proxy.ReportSingleApp(appName, "", "")
diff --git a/plugins/proxy/subcommands.go b/plugins/proxy/subcommands.go
index 1dcb66558a5..58a57a87029 100644
--- a/plugins/proxy/subcommands.go
+++ b/plugins/proxy/subcommands.go
@@ -2,7 +2,6 @@ package proxy
import (
"errors"
- "strings"
"github.com/dokku/dokku/plugins/common"
"github.com/dokku/dokku/plugins/config"
@@ -60,95 +59,6 @@ func CommandEnable(appName string, allApps bool, parallelCount int) error {
return Enable(appName)
}
-// CommandPorts is a cmd wrapper to list proxy port mappings for an app
-func CommandPorts(appName string) error {
- if err := common.VerifyAppName(appName); err != nil {
- return err
- }
-
- return listAppProxyPorts(appName)
-}
-
-// CommandPortsAdd adds proxy port mappings to an app
-func CommandPortsAdd(appName string, portMaps []string) error {
- if err := common.VerifyAppName(appName); err != nil {
- return err
- }
-
- if len(portMaps) == 0 {
- return errors.New("No port mapping specified")
- }
-
- proxyPortMap, err := parseProxyPortMapString(strings.Join(portMaps, " "))
- if err != nil {
- return err
- }
-
- if err := addProxyPorts(appName, proxyPortMap); err != nil {
- return err
- }
-
- return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "add"}...)
-}
-
-// CommandPortsClear clears all proxy port mappings for an app
-func CommandPortsClear(appName string) error {
- if err := common.VerifyAppName(appName); err != nil {
- return err
- }
-
- keys := []string{"DOKKU_PROXY_PORT_MAP"}
- if err := config.UnsetMany(appName, keys, false); err != nil {
- return err
- }
-
- return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "clear"}...)
-}
-
-// CommandPortsRemove removes specific proxy port mappings from an app
-func CommandPortsRemove(appName string, portMaps []string) error {
- if err := common.VerifyAppName(appName); err != nil {
- return err
- }
-
- if len(portMaps) == 0 {
- return errors.New("No port mapping specified")
- }
-
- proxyPortMap, err := parseProxyPortMapString(strings.Join(portMaps, " "))
- if err != nil {
- return err
- }
-
- if err := removeProxyPorts(appName, proxyPortMap); err != nil {
- return err
- }
-
- return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "remove"}...)
-}
-
-// CommandPortsSet sets proxy port mappings for an app
-func CommandPortsSet(appName string, portMaps []string) error {
- if err := common.VerifyAppName(appName); err != nil {
- return err
- }
-
- if len(portMaps) == 0 {
- return errors.New("No port mapping specified")
- }
-
- proxyPortMap, err := parseProxyPortMapString(strings.Join(portMaps, " "))
- if err != nil {
- return err
- }
-
- if err := setProxyPorts(appName, proxyPortMap); err != nil {
- return err
- }
-
- return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "set"}...)
-}
-
// CommandReport displays a proxy report for one or more apps
func CommandReport(appName string, format string, infoFlag string) error {
if len(appName) == 0 {
diff --git a/plugins/proxy/triggers.go b/plugins/proxy/triggers.go
index 626f95a3009..49c0fef0699 100644
--- a/plugins/proxy/triggers.go
+++ b/plugins/proxy/triggers.go
@@ -2,8 +2,6 @@ package proxy
import (
"fmt"
-
- "github.com/dokku/dokku/plugins/config"
)
// TriggerProxyIsEnabled prints true or false depending on whether the proxy is enabled
@@ -24,69 +22,3 @@ func TriggerProxyType(appName string) error {
return nil
}
-
-// TriggerPostCertsRemove unsets port config vars after SSL cert is added
-func TriggerPostCertsRemove(appName string) error {
- keys := []string{"DOKKU_PROXY_SSL_PORT"}
- if err := config.UnsetMany(appName, keys, false); err != nil {
- return err
- }
-
- return removeProxyPorts(appName, filterAppProxyPorts(appName, "https", 443))
-}
-
-// TriggerPostCertsUpdate sets port config vars after SSL cert is added
-func TriggerPostCertsUpdate(appName string) error {
- port := config.GetWithDefault(appName, "DOKKU_PROXY_PORT", "")
- sslPort := config.GetWithDefault(appName, "DOKKU_PROXY_SSL_PORT", "")
- proxyPortMap := getProxyPortMap(appName)
-
- toUnset := []string{}
- if port == "80" {
- toUnset = append(toUnset, "DOKKU_PROXY_PORT")
- }
- if sslPort == "443" {
- toUnset = append(toUnset, "DOKKU_PROXY_SSL_PORT")
- }
-
- if len(toUnset) > 0 {
- if err := config.UnsetMany(appName, toUnset, false); err != nil {
- return err
- }
- }
-
- var http80Ports []PortMap
- for _, portMap := range proxyPortMap {
- if portMap.Scheme == "http" && portMap.HostPort == 80 {
- http80Ports = append(http80Ports, portMap)
- }
- }
-
- if len(http80Ports) > 0 {
- var https443Ports []PortMap
- for _, portMap := range proxyPortMap {
- if portMap.Scheme == "https" && portMap.HostPort == 443 {
- https443Ports = append(https443Ports, portMap)
- }
- }
-
- if err := removeProxyPorts(appName, https443Ports); err != nil {
- return err
- }
-
- var toAdd []PortMap
- for _, portMap := range http80Ports {
- toAdd = append(toAdd, PortMap{
- Scheme: "https",
- HostPort: 443,
- ContainerPort: portMap.ContainerPort,
- })
- }
-
- if err := addProxyPorts(appName, toAdd); err != nil {
- return err
- }
- }
-
- return nil
-}
diff --git a/plugins/repo/go.mod b/plugins/repo/go.mod
index b8490692f09..e2b67dbc3f4 100644
--- a/plugins/repo/go.mod
+++ b/plugins/repo/go.mod
@@ -4,14 +4,12 @@ go 1.19
require (
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
- github.com/dokku/dokku/plugins/config v0.0.0-00010101000000-000000000000
github.com/spf13/pflag v1.0.5
)
require (
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
- github.com/joho/godotenv v1.2.0 // indirect
github.com/otiai10/copy v1.12.0 // indirect
github.com/ryanuber/columnize v2.1.2+incompatible // indirect
golang.org/x/sync v0.3.0 // indirect
diff --git a/plugins/repo/go.sum b/plugins/repo/go.sum
index 1a7ae7db219..a7b423b1ca5 100644
--- a/plugins/repo/go.sum
+++ b/plugins/repo/go.sum
@@ -3,8 +3,6 @@ github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcju
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
-github.com/joho/godotenv v1.2.0 h1:vGTvz69FzUFp+X4/bAkb0j5BoLC+9bpqTWY8mjhA9pc=
-github.com/joho/godotenv v1.2.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY=
github.com/otiai10/copy v1.12.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww=
diff --git a/tests/unit/apps_2.bats b/tests/unit/apps_2.bats
index 2afb61fa827..ce91b5e7897 100644
--- a/tests/unit/apps_2.bats
+++ b/tests/unit/apps_2.bats
@@ -114,7 +114,7 @@ teardown() {
echo "output: $output"
echo "status: $status"
assert_success
- run /bin/bash -c "dokku --quiet proxy:ports app-without-ssl | xargs"
+ run /bin/bash -c "dokku --quiet ports:list app-without-ssl | xargs"
echo "output: $output"
echo "status: $status"
assert_output "http 80 5000"
diff --git a/tests/unit/caddy.bats b/tests/unit/caddy.bats
index 2362ababdc7..7a3c38651ec 100644
--- a/tests/unit/caddy.bats
+++ b/tests/unit/caddy.bats
@@ -137,7 +137,7 @@ teardown() {
assert_success
assert_output "$TEST_APP.dokku.me"
- run /bin/bash -c "dokku proxy:report $TEST_APP --proxy-port-map"
+ run /bin/bash -c "dokku ports:report $TEST_APP --ports-map"
echo "output: $output"
echo "status: $status"
assert_output "http:80:5000"
diff --git a/tests/unit/haproxy.bats b/tests/unit/haproxy.bats
index cf74e6f6771..faa757bf122 100644
--- a/tests/unit/haproxy.bats
+++ b/tests/unit/haproxy.bats
@@ -154,7 +154,7 @@ teardown() {
assert_success
assert_output "true"
- run /bin/bash -c "dokku proxy:report $TEST_APP --proxy-port-map"
+ run /bin/bash -c "dokku ports:report $TEST_APP --ports-map"
echo "output: $output"
echo "status: $status"
assert_output "http:80:5000"
diff --git a/tests/unit/nginx-vhosts_3.bats b/tests/unit/nginx-vhosts_3.bats
index babc690c5fd..0a7ad5fa7c2 100644
--- a/tests/unit/nginx-vhosts_3.bats
+++ b/tests/unit/nginx-vhosts_3.bats
@@ -18,14 +18,14 @@ teardown() {
@test "(nginx-vhosts) grpc endpoint" {
deploy_app gogrpc
- dokku proxy:ports-add "$TEST_APP" "grpc:80:50051"
+ dokku ports:add "$TEST_APP" "grpc:80:50051"
run /bin/bash -c "docker run --rm ${TEST_APP}-docker-image /go/bin/greeter_client -address ${TEST_APP}.dokku.me:80 -name grpc"
assert_output "Greeting: Hello grpc"
}
@test "(nginx-vhosts) grpc endpoint on a port other than 80" {
deploy_app gogrpc
- dokku proxy:ports-add "$TEST_APP" "grpc:8080:50051"
+ dokku ports:add "$TEST_APP" "grpc:8080:50051"
run /bin/bash -c "docker run --rm ${TEST_APP}-docker-image /go/bin/greeter_client -address ${TEST_APP}.dokku.me:8080 -name grpc8080"
assert_output "Greeting: Hello grpc8080"
}
@@ -33,7 +33,7 @@ teardown() {
@test "(nginx-vhosts) grpcs endpoint" {
setup_test_tls
deploy_app gogrpc
- dokku proxy:ports-add "$TEST_APP" "grpcs:443:50051"
+ dokku ports:add "$TEST_APP" "grpcs:443:50051"
run /bin/bash -c "docker run --rm ${TEST_APP}-docker-image /go/bin/greeter_client -address ${TEST_APP}.dokku.me:443 -name grpcs -tls"
assert_output "Greeting: Hello grpcs"
}
diff --git a/tests/unit/nginx-vhosts_8.bats b/tests/unit/nginx-vhosts_8.bats
index 248296737ac..d0b02ae4c1c 100644
--- a/tests/unit/nginx-vhosts_8.bats
+++ b/tests/unit/nginx-vhosts_8.bats
@@ -125,7 +125,7 @@ teardown() {
assert_output_contains "Ignoring detected https port mapping without an accompanying ssl certificate" 0
teardown_test_tls
- run /bin/bash -c "dokku proxy:report $TEST_APP --proxy-port-map"
+ run /bin/bash -c "dokku ports:report $TEST_APP --ports-map"
echo "output: $output"
echo "status: $status"
assert_output "http:80:5000 https:443:5000"
@@ -135,7 +135,7 @@ teardown() {
echo "status: $status"
assert_output_contains "Ignoring detected https port mapping without an accompanying ssl certificate" 1
- run /bin/bash -c "dokku proxy:report $TEST_APP --proxy-port-map"
+ run /bin/bash -c "dokku ports:report $TEST_APP --ports-map"
echo "output: $output"
echo "status: $status"
assert_output "http:80:5000 https:443:5000"
diff --git a/tests/unit/ports.bats b/tests/unit/ports.bats
new file mode 100644
index 00000000000..2bef9aa78fa
--- /dev/null
+++ b/tests/unit/ports.bats
@@ -0,0 +1,106 @@
+#!/usr/bin/env bats
+
+load test_helper
+
+setup() {
+ global_setup
+ [[ -f "$DOKKU_ROOT/VHOST" ]] && cp -fp "$DOKKU_ROOT/VHOST" "$DOKKU_ROOT/VHOST.bak"
+ create_app
+}
+
+teardown() {
+ destroy_app 0 $TEST_APP
+ [[ -f "$DOKKU_ROOT/VHOST.bak" ]] && mv "$DOKKU_ROOT/VHOST.bak" "$DOKKU_ROOT/VHOST" && chown dokku:dokku "$DOKKU_ROOT/VHOST"
+ global_teardown
+}
+
+@test "(ports) ports:help" {
+ run /bin/bash -c "dokku ports"
+ echo "output: $output"
+ echo "status: $status"
+ assert_output_contains "Manage ports for an app"
+ help_output="$output"
+
+ run /bin/bash -c "dokku ports:help"
+ echo "output: $output"
+ echo "status: $status"
+ assert_output_contains "Manage ports for an app"
+ assert_output "$help_output"
+}
+
+@test "(ports) ports subcommands (list/add/set/remove/clear)" {
+ run /bin/bash -c "dokku ports:set $TEST_APP http:1234:5001"
+ echo "output: $output"
+ echo "status: $status"
+ assert_success
+
+ run /bin/bash -c "dokku --quiet ports:list $TEST_APP | xargs"
+ echo "output: $output"
+ echo "status: $status"
+ assert_output "http 1234 5001"
+
+ run /bin/bash -c "dokku ports:add $TEST_APP http:8080:5002 https:8443:5003"
+ echo "output: $output"
+ echo "status: $status"
+ assert_success
+
+ run /bin/bash -c "dokku --quiet ports:list $TEST_APP | xargs"
+ echo "output: $output"
+ echo "status: $status"
+ assert_output "http 1234 5001 http 8080 5002 https 8443 5003"
+
+ run /bin/bash -c "dokku ports:set $TEST_APP http:8080:5000 https:8443:5000 http:1234:5001"
+ echo "output: $output"
+ echo "status: $status"
+ assert_success
+
+ run /bin/bash -c "dokku --quiet ports:list $TEST_APP | xargs"
+ echo "output: $output"
+ echo "status: $status"
+ assert_output "http 1234 5001 http 8080 5000 https 8443 5000"
+
+ run /bin/bash -c "dokku ports:remove $TEST_APP 8080"
+ echo "output: $output"
+ echo "status: $status"
+ assert_success
+
+ run /bin/bash -c "dokku --quiet ports:list $TEST_APP | xargs"
+ echo "output: $output"
+ echo "status: $status"
+ assert_output "http 1234 5001 https 8443 5000"
+
+ run /bin/bash -c "dokku ports:remove $TEST_APP http:1234:5001"
+ echo "output: $output"
+ echo "status: $status"
+ assert_success
+
+ run /bin/bash -c "dokku --quiet ports:list $TEST_APP | xargs"
+ echo "output: $output"
+ echo "status: $status"
+ assert_output "https 8443 5000"
+
+ run /bin/bash -c "dokku ports:clear $TEST_APP"
+ echo "output: $output"
+ echo "status: $status"
+ assert_success
+
+ run /bin/bash -c "dokku --quiet ports:list $TEST_APP | xargs"
+ echo "output: $output"
+ echo "status: $status"
+ assert_output "http 80 5000"
+}
+
+@test "(ports) ports:add (post-deploy add)" {
+ deploy_app
+ run /bin/bash -c "dokku ports:add $TEST_APP http:8080:5000 http:8081:5000"
+ echo "output: $output"
+ echo "status: $status"
+ assert_success
+
+ URLS="$(dokku --quiet urls "$TEST_APP")"
+ for URL in $URLS; do
+ assert_http_success $URL
+ done
+ assert_http_success "http://$TEST_APP.dokku.me:8080"
+ assert_http_success "http://$TEST_APP.dokku.me:8081"
+}
diff --git a/tests/unit/proxied-app.bats b/tests/unit/proxied-app.bats
index e16928634dd..3d4ed454842 100644
--- a/tests/unit/proxied-app.bats
+++ b/tests/unit/proxied-app.bats
@@ -29,7 +29,7 @@ teardown() {
echo "status: $status"
assert_success
- run /bin/bash -c "dokku proxy:ports-set $TEST_APP http:80:8080"
+ run /bin/bash -c "dokku ports:set $TEST_APP http:80:8080"
echo "output: $output"
echo "status: $status"
assert_success
diff --git a/tests/unit/proxy.bats b/tests/unit/proxy.bats
index be69693fde1..1de3c9db0c4 100644
--- a/tests/unit/proxy.bats
+++ b/tests/unit/proxy.bats
@@ -113,80 +113,3 @@ teardown() {
assert_not_external_port $(<$CID_FILE)
done
}
-
-@test "(proxy) proxy:ports (list/add/set/remove/clear)" {
- run /bin/bash -c "dokku proxy:ports-set $TEST_APP http:1234:5001"
- echo "output: $output"
- echo "status: $status"
- assert_success
-
- run /bin/bash -c "dokku --quiet proxy:ports $TEST_APP | xargs"
- echo "output: $output"
- echo "status: $status"
- assert_output "http 1234 5001"
-
- run /bin/bash -c "dokku proxy:ports-add $TEST_APP http:8080:5002 https:8443:5003"
- echo "output: $output"
- echo "status: $status"
- assert_success
-
- run /bin/bash -c "dokku --quiet proxy:ports $TEST_APP | xargs"
- echo "output: $output"
- echo "status: $status"
- assert_output "http 1234 5001 http 8080 5002 https 8443 5003"
-
- run /bin/bash -c "dokku proxy:ports-set $TEST_APP http:8080:5000 https:8443:5000 http:1234:5001"
- echo "output: $output"
- echo "status: $status"
- assert_success
-
- run /bin/bash -c "dokku --quiet proxy:ports $TEST_APP | xargs"
- echo "output: $output"
- echo "status: $status"
- assert_output "http 1234 5001 http 8080 5000 https 8443 5000"
-
- run /bin/bash -c "dokku proxy:ports-remove $TEST_APP 8080"
- echo "output: $output"
- echo "status: $status"
- assert_success
-
- run /bin/bash -c "dokku --quiet proxy:ports $TEST_APP | xargs"
- echo "output: $output"
- echo "status: $status"
- assert_output "http 1234 5001 https 8443 5000"
-
- run /bin/bash -c "dokku proxy:ports-remove $TEST_APP http:1234:5001"
- echo "output: $output"
- echo "status: $status"
- assert_success
-
- run /bin/bash -c "dokku --quiet proxy:ports $TEST_APP | xargs"
- echo "output: $output"
- echo "status: $status"
- assert_output "https 8443 5000"
-
- run /bin/bash -c "dokku proxy:ports-clear $TEST_APP"
- echo "output: $output"
- echo "status: $status"
- assert_success
-
- run /bin/bash -c "dokku --quiet proxy:ports $TEST_APP | xargs"
- echo "output: $output"
- echo "status: $status"
- assert_output "http 80 5000"
-}
-
-@test "(proxy) proxy:ports (post-deploy add)" {
- deploy_app
- run /bin/bash -c "dokku proxy:ports-add $TEST_APP http:8080:5000 http:8081:5000"
- echo "output: $output"
- echo "status: $status"
- assert_success
-
- URLS="$(dokku --quiet urls "$TEST_APP")"
- for URL in $URLS; do
- assert_http_success $URL
- done
- assert_http_success "http://$TEST_APP.dokku.me:8080"
- assert_http_success "http://$TEST_APP.dokku.me:8081"
-}
diff --git a/tests/unit/traefik.bats b/tests/unit/traefik.bats
index a45725aef53..cfdb343d7e6 100644
--- a/tests/unit/traefik.bats
+++ b/tests/unit/traefik.bats
@@ -233,7 +233,7 @@ teardown() {
assert_success
assert_output "5000"
- run /bin/bash -c "dokku proxy:report $TEST_APP --proxy-port-map"
+ run /bin/bash -c "dokku ports:report $TEST_APP --ports-map"
echo "output: $output"
echo "status: $status"
assert_output "http:80:5000"