package network import ( "encoding/json" "errors" "fmt" "os" "strings" "github.com/dokku/dokku/plugins/common" ) // CommandCreate is an alias for "docker network create" func CommandCreate(networkName string) error { common.LogInfo1Quiet(fmt.Sprintf("Creating network %v", networkName)) result, err := common.CallExecCommand(common.ExecCommandInput{ Command: common.DockerBin(), Args: []string{"network", "create", "--attachable", "--label", fmt.Sprintf("com.dokku.network-name=%v", networkName), networkName}, }) if err != nil { return fmt.Errorf("Unable to create network: %w", err) } if result.ExitCode != 0 { return fmt.Errorf("Unable to create network: %s", result.StderrContents()) } return err } // CommandDestroy is an alias for "docker network rm" func CommandDestroy(networkName string, forceDestroy bool) error { if os.Getenv("DOKKU_APPS_FORCE_DELETE") == "1" { forceDestroy = true } if !forceDestroy { if err := common.AskForDestructiveConfirmation(networkName, "network"); err != nil { return err } } common.LogInfo1Quiet(fmt.Sprintf("Destroying network %v", networkName)) result, err := common.CallExecCommand(common.ExecCommandInput{ Command: common.DockerBin(), Args: []string{"network", "rm", networkName}, }) if err != nil { return fmt.Errorf("Unable to destroy network: %w", err) } if result.ExitCode != 0 { return fmt.Errorf("Unable to destroy network: %s", result.StderrContents()) } return nil } // CommandExists checks if a network exists func CommandExists(networkName string) error { if networkName == "" { return errors.New("No network name specified") } exists, err := networkExists(networkName) if err != nil { return err } if exists { common.LogInfo1Quiet("Network exists") } else { return errors.New("Network does not exist") } return nil } // CommandInfo is an alias for "docker network inspect" func CommandInfo(networkName string, format string) error { if networkName == "" { return errors.New("No network name specified") } if format != "json" && format != "text" { return errors.New("Invalid format specified, use either text or json") } networks, err := getNetworks() if err != nil { return err } network, ok := networks[networkName] if !ok { return errors.New("Network does not exist") } if format == "json" { out, err := json.Marshal(network) if err != nil { return err } common.Log(string(out)) return nil } length := 10 common.LogInfo2Quiet(fmt.Sprintf("%s network information", networkName)) common.LogVerbose(fmt.Sprintf("%s%s", common.RightPad("ID:", length, " "), network.ID)) common.LogVerbose(fmt.Sprintf("%s%s", common.RightPad("Name:", length, " "), network.Name)) common.LogVerbose(fmt.Sprintf("%s%s", common.RightPad("Driver:", length, " "), network.Driver)) common.LogVerbose(fmt.Sprintf("%s%s", common.RightPad("Scope:", length, " "), network.Scope)) return nil } // CommandList is an alias for "docker network ls" func CommandList(format string) error { networks, err := getNetworks() if err != nil { return err } if format == "json" { networkList := []DockerNetwork{} for _, network := range networks { networkList = append(networkList, network) } out, err := json.Marshal(networkList) if err != nil { return err } common.Log(string(out)) return nil } common.LogInfo2Quiet("Networks") for _, network := range networks { fmt.Println(network.Name) } return nil } // CommandRebuildall rebuilds network settings for all apps func CommandRebuildall() error { apps, err := common.DokkuApps() if err != nil { if errors.Is(err, common.NoAppsExist) { common.LogWarn(err.Error()) return nil } return err } for _, appName := range apps { err = BuildConfig(appName) if err != nil { return err } } return nil } // CommandReport displays a network 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 { if errors.Is(err, common.NoAppsExist) { common.LogWarn(err.Error()) return nil } return err } for _, appName := range apps { if err := ReportSingleApp(appName, format, infoFlag); err != nil { return err } } return nil } return ReportSingleApp(appName, format, infoFlag) } // CommandSet set or clear a network property for an app func CommandSet(appName string, property string, value string, values []string) error { if appName != "--global" { if err := common.VerifyAppName(appName); err != nil { return err } } if property == "bind-all-interfaces" && value == "" { value = "false" } attachProperties := map[string]bool{ "attach-post-create": true, "attach-post-deploy": true, } invalidNetworks := map[string]bool{ "host": true, "bridge": true, } 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, 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) return nil }