swarmd/cmd/swarmctl/service/flagparser/resource.go
package flagparser
import (
"fmt"
"math/big"
"github.com/docker/go-units"
"github.com/moby/swarmkit/v2/api"
"github.com/moby/swarmkit/v2/api/genericresource"
"github.com/spf13/pflag"
)
func parseResourceCPU(flags *pflag.FlagSet, resources *api.Resources, name string) error {
cpu, err := flags.GetString(name)
if err != nil {
return err
}
nanoCPUs, ok := new(big.Rat).SetString(cpu)
if !ok {
return fmt.Errorf("invalid cpu: %s", cpu)
}
cpuRat := new(big.Rat).Mul(nanoCPUs, big.NewRat(1e9, 1))
if !cpuRat.IsInt() {
return fmt.Errorf("CPU value cannot have more than 9 decimal places: %s", cpu)
}
resources.NanoCPUs = cpuRat.Num().Int64()
return nil
}
func parseResourceMemory(flags *pflag.FlagSet, resources *api.Resources, name string) error {
memory, err := flags.GetString(name)
if err != nil {
return err
}
bytes, err := units.RAMInBytes(memory)
if err != nil {
return err
}
resources.MemoryBytes = bytes
return nil
}
func parseResource(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
if flags.Changed("memory-reservation") {
if spec.Task.Resources == nil {
spec.Task.Resources = &api.ResourceRequirements{}
}
if spec.Task.Resources.Reservations == nil {
spec.Task.Resources.Reservations = &api.Resources{}
}
if err := parseResourceMemory(flags, spec.Task.Resources.Reservations, "memory-reservation"); err != nil {
return err
}
}
if flags.Changed("memory-limit") {
if spec.Task.Resources == nil {
spec.Task.Resources = &api.ResourceRequirements{}
}
if spec.Task.Resources.Limits == nil {
spec.Task.Resources.Limits = &api.Resources{}
}
if err := parseResourceMemory(flags, spec.Task.Resources.Limits, "memory-limit"); err != nil {
return err
}
}
if flags.Changed("cpu-reservation") {
if spec.Task.Resources == nil {
spec.Task.Resources = &api.ResourceRequirements{}
}
if spec.Task.Resources.Reservations == nil {
spec.Task.Resources.Reservations = &api.Resources{}
}
if err := parseResourceCPU(flags, spec.Task.Resources.Reservations, "cpu-reservation"); err != nil {
return err
}
}
if flags.Changed("cpu-limit") {
if spec.Task.Resources == nil {
spec.Task.Resources = &api.ResourceRequirements{}
}
if spec.Task.Resources.Limits == nil {
spec.Task.Resources.Limits = &api.Resources{}
}
if err := parseResourceCPU(flags, spec.Task.Resources.Limits, "cpu-limit"); err != nil {
return err
}
}
if flags.Changed("generic-resources") {
if spec.Task.Resources == nil {
spec.Task.Resources = &api.ResourceRequirements{}
}
if spec.Task.Resources.Reservations == nil {
spec.Task.Resources.Reservations = &api.Resources{}
}
cmd, err := flags.GetString("generic-resources")
if err != nil {
return err
}
spec.Task.Resources.Reservations.Generic, err = genericresource.ParseCmd(cmd)
if err != nil {
return err
}
err = genericresource.ValidateTask(spec.Task.Resources.Reservations)
if err != nil {
return err
}
}
if flags.Changed("ulimit") {
container := spec.Task.GetContainer()
if container == nil {
return nil
}
ulimits, err := flags.GetStringSlice("ulimit")
if err != nil {
return err
}
container.Ulimits = make([]*api.ContainerSpec_Ulimit, len(ulimits))
for i, ulimit := range ulimits {
parsed, err := units.ParseUlimit(ulimit)
if err != nil {
return err
}
container.Ulimits[i] = &api.ContainerSpec_Ulimit{
Name: parsed.Name,
Soft: parsed.Soft,
Hard: parsed.Hard,
}
}
}
return nil
}