feat: add support for specifying multiple networks on a given app

Closes #5314
This commit is contained in:
Jose Diaz-Gonzalez
2023-05-28 21:21:26 -04:00
parent 40b20e0c08
commit 60b343470b
7 changed files with 104 additions and 42 deletions

View File

@@ -173,6 +173,13 @@ dokku network:set node-js-app attach-post-deploy other-test-network
dokku network:set node-js-app initial-network global-network
```
Multiple networks can also be specified for the `attach-post-create` and `attach-post-deploy` phases.
```shell
# one or more networks can be specified
dokku network:set node-js-app attach-post-create test-network test-network-2
```
Setting the `attach` network property to an empty value will de-associate the container with the network.
```shell

View File

@@ -596,6 +596,15 @@ func (err *AppDoesNotExist) Error() string {
return fmt.Sprintf("App %s does not exist", err.appName)
}
// VarArgs skips a number of incoming arguments, returning what is left over
func VarArgs(arguments []string, skip int) []string {
if len(arguments) <= skip {
return []string{}
}
return arguments[skip:]
}
// VerifyAppName checks if an app conforming to either the old or new
// naming conventions exists
func VerifyAppName(appName string) error {

View File

@@ -23,10 +23,10 @@ Additional commands:`
network:exists <network>, Checks if a docker network exists
network:info <network>, Outputs information about a docker network
network:list, Lists all docker networks
network:report [<app>] [<flag>], Displays a network report for one or more apps
network:rebuild <app>, Rebuilds network settings for an app
network:rebuildall, Rebuild network settings for all apps
network:set <app> <property> (<value>), Set or clear a network property for an app
network:report [<app>] [<flag>], Displays a network report for one or more apps
network:set <app> <property> (<value>...), Set or clear a network property for an app
`
)

View File

@@ -67,12 +67,14 @@ func main() {
appName := args.Arg(0)
property := args.Arg(1)
value := args.Arg(2)
values := common.VarArgs(args.Args(), 2)
if *global {
appName = "--global"
property = args.Arg(0)
value = args.Arg(1)
values = common.VarArgs(args.Args(), 1)
}
err = network.CommandSet(appName, property, value)
err = network.CommandSet(appName, property, value, values)
default:
err = fmt.Errorf("Invalid plugin subcommand call: %s", subcommand)
}

View File

@@ -141,7 +141,7 @@ func CommandReport(appName string, format string, infoFlag string) error {
}
// CommandSet set or clear a network property for an app
func CommandSet(appName string, property string, value string) error {
func CommandSet(appName string, property string, value string, values []string) error {
if appName != "--global" {
if err := common.VerifyAppName(appName); err != nil {
return err
@@ -152,7 +152,7 @@ func CommandSet(appName string, property string, value string) error {
value = "false"
}
attachProperites := map[string]bool{
attachProperties := map[string]bool{
"attach-post-create": true,
"attach-post-deploy": true,
}
@@ -161,14 +161,17 @@ func CommandSet(appName string, property string, value string) error {
"host": true,
"bridge": true,
}
if attachProperites[property] {
if invalidNetworks[value] {
return errors.New("Invalid network name specified for attach")
}
if attachProperties[property] {
for _, networkName := range values {
if invalidNetworks[networkName] {
return fmt.Errorf("Invalid network name specified for attach: %s", networkName)
}
if isConflictingPropertyValue(appName, property, value) {
return errors.New("Network name already associated with this app")
if isConflictingPropertyValue(appName, property, networkName) {
return fmt.Errorf("Network name already associated with this app: %s", networkName)
}
}
value = strings.Join(values, ",")
}
common.CommandPropertySet("network", appName, property, value, DefaultProperties, GlobalProperties)

View File

@@ -225,22 +225,26 @@ func TriggerPostContainerCreate(containerType string, containerID string, appNam
}
networkName := reportComputedAttachPostCreate(appName)
if networkName == "" {
networks := reportComputedAttachPostCreate(appName)
if networks == "" {
return nil
}
exists, err := networkExists(networkName)
if err != nil {
return err
for _, networkName := range strings.Split(networks, ",") {
exists, err := networkExists(networkName)
if err != nil {
return err
}
if !exists {
return fmt.Errorf("Network %v does not exist", networkName)
}
return attachAppToNetwork(containerID, networkName, appName, phase, processType)
}
if !exists {
return fmt.Errorf("Network %v does not exist", networkName)
}
return attachAppToNetwork(containerID, networkName, appName, phase, processType)
return nil
}
// TriggerPostCreate sets bind-all-interfaces to false by default
@@ -260,34 +264,37 @@ func TriggerPostDelete(appName string) error {
// TriggerCorePostDeploy associates the container with a specified network
func TriggerCorePostDeploy(appName string) error {
networkName := reportComputedAttachPostDeploy(appName)
if networkName == "" {
networks := reportComputedAttachPostDeploy(appName)
if networks == "" {
return nil
}
common.LogInfo1Quiet(fmt.Sprintf("Associating app with network %s", networkName))
containerIDs, err := common.GetAppRunningContainerIDs(appName, "")
if err != nil {
return err
}
exists, err := networkExists(networkName)
if err != nil {
return err
}
if !exists {
return fmt.Errorf("Network %v does not exist", networkName)
}
for _, containerID := range containerIDs {
processType, err := common.DockerInspect(containerID, "{{ index .Config.Labels \"com.dokku.process-type\"}}")
for _, networkName := range strings.Split(networks, ",") {
common.LogInfo1Quiet(fmt.Sprintf("Associating app with network %s", networkName))
containerIDs, err := common.GetAppRunningContainerIDs(appName, "")
if err != nil {
return err
}
if err := attachAppToNetwork(containerID, networkName, appName, "deploy", processType); err != nil {
exists, err := networkExists(networkName)
if err != nil {
return err
}
if !exists {
return fmt.Errorf("Network %v does not exist", networkName)
}
for _, containerID := range containerIDs {
processType, err := common.DockerInspect(containerID, "{{ index .Config.Labels \"com.dokku.process-type\"}}")
if err != nil {
return err
}
if err := attachAppToNetwork(containerID, networkName, appName, "deploy", processType); err != nil {
return err
}
}
}
return nil
}

View File

@@ -156,11 +156,21 @@ teardown() {
echo "status: $status"
assert_success
run /bin/bash -c "dokku network:create create-network-2"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku network:create deploy-network"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku network:create deploy-network-2"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku network:create initial-network"
echo "output: $output"
echo "status: $status"
@@ -208,6 +218,22 @@ teardown() {
assert_success
assert_http_success "${TEST_APP}.dokku.me"
run /bin/bash -c "dokku network:set $TEST_APP attach-post-create create-network create-network-2"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku network:set $TEST_APP attach-post-deploy deploy-network deploy-network-2"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku ps:rebuild $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
assert_http_success "${TEST_APP}.dokku.me"
run /bin/bash -c "dokku --force network:destroy create-network"
echo "output: $output"
echo "status: $status"
@@ -224,7 +250,15 @@ teardown() {
assert_success
# necessary in order to remove networks in use by "dead" containers
docker container prune --force
run /bin/bash -c "docker container prune --force"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "docker container ls -a"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku --force network:destroy create-network"
echo "output: $output"