feat: add support for specifying multiple networks on a given app
Closes #5314
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
`
|
||||
)
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user