feat: simplify flag parsing in resource plugin
Commands should be written such that they take arguments as is.
This commit is contained in:
130
plugins/resource/functions.go
Normal file
130
plugins/resource/functions.go
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
package resource
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/dokku/dokku/plugins/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func clearByResourceType(appName string, processType string, resourceType string) {
|
||||||
|
noun := "limits"
|
||||||
|
if resourceType == "reserve" {
|
||||||
|
noun = "reservation"
|
||||||
|
}
|
||||||
|
|
||||||
|
message := fmt.Sprintf("clearing %v %v", appName, noun)
|
||||||
|
if processType != "_default_" && processType != "" {
|
||||||
|
message = fmt.Sprintf("%v (%v)", message, processType)
|
||||||
|
}
|
||||||
|
common.LogInfo2Quiet(message)
|
||||||
|
|
||||||
|
if processType == "" {
|
||||||
|
resources, err := common.PropertyGetAll("resource", appName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for key := range resources {
|
||||||
|
common.PropertyDelete("resource", appName, key)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resources := []string{
|
||||||
|
"cpu",
|
||||||
|
"memory",
|
||||||
|
"memory-swap",
|
||||||
|
"network",
|
||||||
|
"network-ingress",
|
||||||
|
"network-egress",
|
||||||
|
"nvidia-gpu",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, key := range resources {
|
||||||
|
property := propertyKey(processType, resourceType, key)
|
||||||
|
common.PropertyDelete("resource", appName, property)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setResourceType(appName string, processType string, r Resource, resourceType string) error {
|
||||||
|
if len(processType) == 0 {
|
||||||
|
processType = "_default_"
|
||||||
|
}
|
||||||
|
|
||||||
|
resources := map[string]string{
|
||||||
|
"cpu": r.CPU,
|
||||||
|
"memory": r.Memory,
|
||||||
|
"memory-swap": r.MemorySwap,
|
||||||
|
"network": r.Network,
|
||||||
|
"network-ingress": r.NetworkIngress,
|
||||||
|
"network-egress": r.NetworkEgress,
|
||||||
|
"nvidia-gpu": r.NvidiaGPU,
|
||||||
|
}
|
||||||
|
|
||||||
|
hasValues := false
|
||||||
|
for _, value := range resources {
|
||||||
|
if value != "" {
|
||||||
|
hasValues = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasValues {
|
||||||
|
reportResourceType(appName, processType, resourceType)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
noun := "limits"
|
||||||
|
if resourceType == "reserve" {
|
||||||
|
noun = "reservation"
|
||||||
|
}
|
||||||
|
message := fmt.Sprintf("Setting resource %v for %v", noun, appName)
|
||||||
|
if processType != "_default_" {
|
||||||
|
message = fmt.Sprintf("%v (%v)", message, processType)
|
||||||
|
}
|
||||||
|
common.LogInfo2Quiet(message)
|
||||||
|
|
||||||
|
for key, value := range resources {
|
||||||
|
if value == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
common.LogVerbose(fmt.Sprintf("%v: %v", key, value))
|
||||||
|
property := propertyKey(processType, resourceType, key)
|
||||||
|
err := common.PropertyWrite("resource", appName, property, value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func reportResourceType(appName string, processType string, resourceType string) {
|
||||||
|
noun := "limits"
|
||||||
|
if resourceType == "reserve" {
|
||||||
|
noun = "reservation"
|
||||||
|
}
|
||||||
|
|
||||||
|
message := fmt.Sprintf("resource %v %v information", noun, appName)
|
||||||
|
if processType == "_default_" {
|
||||||
|
message = fmt.Sprintf("%v [defaults]", message)
|
||||||
|
} else {
|
||||||
|
message = fmt.Sprintf("%v (%v)", message, processType)
|
||||||
|
}
|
||||||
|
common.LogInfo2Quiet(message)
|
||||||
|
|
||||||
|
resources := []string{
|
||||||
|
"cpu",
|
||||||
|
"memory",
|
||||||
|
"memory-swap",
|
||||||
|
"network",
|
||||||
|
"network-ingress",
|
||||||
|
"network-egress",
|
||||||
|
"nvidia-gpu",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, key := range resources {
|
||||||
|
property := propertyKey(processType, resourceType, key)
|
||||||
|
value := common.PropertyGet("resource", appName, property)
|
||||||
|
common.LogVerbose(fmt.Sprintf("%v: %v", key, value))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ func main() {
|
|||||||
networkEgress := args.String("network-egress", "", "network-egress: The amount of egress network bandwidth to limit processes by")
|
networkEgress := args.String("network-egress", "", "network-egress: The amount of egress network bandwidth to limit processes by")
|
||||||
nvidiaGpu := args.String("nvidia-gpu", "", "nvidia-gpu: The number of Nvidia GPUs to limit a process to")
|
nvidiaGpu := args.String("nvidia-gpu", "", "nvidia-gpu: The number of Nvidia GPUs to limit a process to")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
|
appName := args.Arg(0)
|
||||||
|
|
||||||
resources := resource.Resource{
|
resources := resource.Resource{
|
||||||
CPU: *cpu,
|
CPU: *cpu,
|
||||||
@@ -39,17 +40,19 @@ func main() {
|
|||||||
NvidiaGPU: *nvidiaGpu,
|
NvidiaGPU: *nvidiaGpu,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = resource.CommandLimit(args.Args(), *processType, resources)
|
err = resource.CommandLimit(appName, *processType, resources)
|
||||||
case "limit-clear":
|
case "limit-clear":
|
||||||
args := flag.NewFlagSet("resource:limit-clear", flag.ExitOnError)
|
args := flag.NewFlagSet("resource:limit-clear", flag.ExitOnError)
|
||||||
processType := args.String("process-type", "", "process-type: A process type to clear")
|
processType := args.String("process-type", "", "process-type: A process type to clear")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
err = resource.CommandLimitClear(args.Args(), *processType)
|
appName := args.Arg(0)
|
||||||
|
err = resource.CommandLimitClear(appName, *processType)
|
||||||
case "report":
|
case "report":
|
||||||
flag.Parse()
|
args := flag.NewFlagSet("resource:report", flag.ExitOnError)
|
||||||
appName := flag.Arg(1)
|
args.Parse(os.Args[2:])
|
||||||
infoFlag := flag.Arg(2)
|
appName := args.Arg(0)
|
||||||
resource.CommandReport(appName, infoFlag)
|
infoFlag := args.Arg(1)
|
||||||
|
err = resource.CommandReport(appName, infoFlag)
|
||||||
case "reserve":
|
case "reserve":
|
||||||
args := flag.NewFlagSet("resource:reserve", flag.ExitOnError)
|
args := flag.NewFlagSet("resource:reserve", flag.ExitOnError)
|
||||||
processType := args.String("process-type", "", "process-type: A process type to manage")
|
processType := args.String("process-type", "", "process-type: A process type to manage")
|
||||||
@@ -61,6 +64,7 @@ func main() {
|
|||||||
networkEgress := args.String("network-egress", "", "network-egress: The amount of egress network bandwidth to reserve for processes")
|
networkEgress := args.String("network-egress", "", "network-egress: The amount of egress network bandwidth to reserve for processes")
|
||||||
nvidiaGpu := args.String("nvidia-gpu", "", "nvidia-gpu: The number of Nvidia GPUs to resource for a process")
|
nvidiaGpu := args.String("nvidia-gpu", "", "nvidia-gpu: The number of Nvidia GPUs to resource for a process")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
|
appName := args.Arg(0)
|
||||||
|
|
||||||
resources := resource.Resource{
|
resources := resource.Resource{
|
||||||
CPU: *cpu,
|
CPU: *cpu,
|
||||||
@@ -72,12 +76,13 @@ func main() {
|
|||||||
NvidiaGPU: *nvidiaGpu,
|
NvidiaGPU: *nvidiaGpu,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = resource.CommandReserve(args.Args(), *processType, resources)
|
err = resource.CommandReserve(appName, *processType, resources)
|
||||||
case "reserve-clear":
|
case "reserve-clear":
|
||||||
args := flag.NewFlagSet("resource:reserve-clear", flag.ExitOnError)
|
args := flag.NewFlagSet("resource:reserve-clear", flag.ExitOnError)
|
||||||
processType := args.String("process-type", "", "process-type: A process type to clear")
|
processType := args.String("process-type", "", "process-type: A process type to clear")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
err = resource.CommandReserveClear(args.Args(), *processType)
|
appName := args.Arg(0)
|
||||||
|
err = resource.CommandReserveClear(appName, *processType)
|
||||||
default:
|
default:
|
||||||
common.LogFail(fmt.Sprintf("Invalid plugin subcommand call: %s", subcommand))
|
common.LogFail(fmt.Sprintf("Invalid plugin subcommand call: %s", subcommand))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,25 @@
|
|||||||
package resource
|
package resource
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/dokku/dokku/plugins/common"
|
"github.com/dokku/dokku/plugins/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CommandLimit implements resource:limit
|
// CommandLimit implements resource:limit
|
||||||
func CommandLimit(args []string, processType string, r Resource) error {
|
func CommandLimit(appName string, processType string, r Resource) error {
|
||||||
appName, err := getAppName(args)
|
if appName == "" {
|
||||||
if err != nil {
|
return errors.New("Please specify an app to run the command on")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return setResourceType(appName, processType, r, "limit")
|
return setResourceType(appName, processType, r, "limit")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandLimitClear implements resource:limit-clear
|
// CommandLimitClear implements resource:limit-clear
|
||||||
func CommandLimitClear(args []string, processType string) error {
|
func CommandLimitClear(appName string, processType string) error {
|
||||||
appName, err := getAppName(args)
|
if appName == "" {
|
||||||
if err != nil {
|
return errors.New("Please specify an app to run the command on")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clearByResourceType(appName, processType, "limit")
|
clearByResourceType(appName, processType, "limit")
|
||||||
@@ -52,145 +50,20 @@ func CommandReport(appName string, infoFlag string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CommandReserve implements resource:reserve
|
// CommandReserve implements resource:reserve
|
||||||
func CommandReserve(args []string, processType string, r Resource) error {
|
func CommandReserve(appName string, processType string, r Resource) error {
|
||||||
appName, err := getAppName(args)
|
if appName == "" {
|
||||||
if err != nil {
|
return errors.New("Please specify an app to run the command on")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return setResourceType(appName, processType, r, "reserve")
|
return setResourceType(appName, processType, r, "reserve")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandReserveClear implements resource:reserve-clear
|
// CommandReserveClear implements resource:reserve-clear
|
||||||
func CommandReserveClear(args []string, processType string) error {
|
func CommandReserveClear(appName string, processType string) error {
|
||||||
appName, err := getAppName(args)
|
if appName == "" {
|
||||||
if err != nil {
|
return errors.New("Please specify an app to run the command on")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clearByResourceType(appName, processType, "reserve")
|
clearByResourceType(appName, processType, "reserve")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearByResourceType(appName string, processType string, resourceType string) {
|
|
||||||
noun := "limits"
|
|
||||||
if resourceType == "reserve" {
|
|
||||||
noun = "reservation"
|
|
||||||
}
|
|
||||||
|
|
||||||
message := fmt.Sprintf("clearing %v %v", appName, noun)
|
|
||||||
if processType != "_default_" && processType != "" {
|
|
||||||
message = fmt.Sprintf("%v (%v)", message, processType)
|
|
||||||
}
|
|
||||||
common.LogInfo2Quiet(message)
|
|
||||||
|
|
||||||
if processType == "" {
|
|
||||||
resources, err := common.PropertyGetAll("resource", appName)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for key := range resources {
|
|
||||||
common.PropertyDelete("resource", appName, key)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
resources := []string{
|
|
||||||
"cpu",
|
|
||||||
"memory",
|
|
||||||
"memory-swap",
|
|
||||||
"network",
|
|
||||||
"network-ingress",
|
|
||||||
"network-egress",
|
|
||||||
"nvidia-gpu",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, key := range resources {
|
|
||||||
property := propertyKey(processType, resourceType, key)
|
|
||||||
common.PropertyDelete("resource", appName, property)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setResourceType(appName string, processType string, r Resource, resourceType string) error {
|
|
||||||
if len(processType) == 0 {
|
|
||||||
processType = "_default_"
|
|
||||||
}
|
|
||||||
|
|
||||||
resources := map[string]string{
|
|
||||||
"cpu": r.CPU,
|
|
||||||
"memory": r.Memory,
|
|
||||||
"memory-swap": r.MemorySwap,
|
|
||||||
"network": r.Network,
|
|
||||||
"network-ingress": r.NetworkIngress,
|
|
||||||
"network-egress": r.NetworkEgress,
|
|
||||||
"nvidia-gpu": r.NvidiaGPU,
|
|
||||||
}
|
|
||||||
|
|
||||||
hasValues := false
|
|
||||||
for _, value := range resources {
|
|
||||||
if value != "" {
|
|
||||||
hasValues = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hasValues {
|
|
||||||
reportResourceType(appName, processType, resourceType)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
noun := "limits"
|
|
||||||
if resourceType == "reserve" {
|
|
||||||
noun = "reservation"
|
|
||||||
}
|
|
||||||
message := fmt.Sprintf("Setting resource %v for %v", noun, appName)
|
|
||||||
if processType != "_default_" {
|
|
||||||
message = fmt.Sprintf("%v (%v)", message, processType)
|
|
||||||
}
|
|
||||||
common.LogInfo2Quiet(message)
|
|
||||||
|
|
||||||
for key, value := range resources {
|
|
||||||
if value == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
common.LogVerbose(fmt.Sprintf("%v: %v", key, value))
|
|
||||||
property := propertyKey(processType, resourceType, key)
|
|
||||||
err := common.PropertyWrite("resource", appName, property, value)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func reportResourceType(appName string, processType string, resourceType string) {
|
|
||||||
noun := "limits"
|
|
||||||
if resourceType == "reserve" {
|
|
||||||
noun = "reservation"
|
|
||||||
}
|
|
||||||
|
|
||||||
message := fmt.Sprintf("resource %v %v information", noun, appName)
|
|
||||||
if processType == "_default_" {
|
|
||||||
message = fmt.Sprintf("%v [defaults]", message)
|
|
||||||
} else {
|
|
||||||
message = fmt.Sprintf("%v (%v)", message, processType)
|
|
||||||
}
|
|
||||||
common.LogInfo2Quiet(message)
|
|
||||||
|
|
||||||
resources := []string{
|
|
||||||
"cpu",
|
|
||||||
"memory",
|
|
||||||
"memory-swap",
|
|
||||||
"network",
|
|
||||||
"network-ingress",
|
|
||||||
"network-egress",
|
|
||||||
"nvidia-gpu",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, key := range resources {
|
|
||||||
property := propertyKey(processType, resourceType, key)
|
|
||||||
value := common.PropertyGet("resource", appName, property)
|
|
||||||
common.LogVerbose(fmt.Sprintf("%v: %v", key, value))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user