Skip to content

Commit

Permalink
enforce limits are consistent with deploy section
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
  • Loading branch information
ndeloof committed Mar 21, 2024
1 parent 40843e6 commit c37fc59
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 7 deletions.
12 changes: 6 additions & 6 deletions loader/full-struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ func services(workingDir, homeDir string) types.Services {
},
Resources: types.Resources{
Limits: &types.Resource{
NanoCPUs: "0.001",
NanoCPUs: 0.001,
MemoryBytes: 50 * 1024 * 1024,
},
Reservations: &types.Resource{
NanoCPUs: "0.0001",
NanoCPUs: 0.0001,
MemoryBytes: 20 * 1024 * 1024,
GenericResources: []types.GenericResource{
{
Expand Down Expand Up @@ -690,10 +690,10 @@ services:
order: start-first
resources:
limits:
cpus: "0.001"
cpus: 0.001
memory: "52428800"
reservations:
cpus: "0.0001"
cpus: 0.0001
memory: "20971520"
generic_resources:
- discrete_resource_spec:
Expand Down Expand Up @@ -1267,11 +1267,11 @@ func fullExampleJSON(workingDir, homeDir string) string {
},
"resources": {
"limits": {
"cpus": "0.001",
"cpus": 0.001,
"memory": "52428800"
},
"reservations": {
"cpus": "0.0001",
"cpus": 0.0001,
"memory": "20971520",
"generic_resources": [
{
Expand Down
25 changes: 25 additions & 0 deletions loader/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,31 @@ func checkConsistency(project *types.Project) error {
s.Deploy.Replicas = s.Scale
}

if s.CPUS != 0 && s.Deploy != nil {
if s.Deploy.Resources.Limits != nil && s.Deploy.Resources.Limits.NanoCPUs.Value() != s.CPUS {
return fmt.Errorf("services.%s: can't set distinct values on 'cpus' and 'deploy.resources.limits.cpus': %w",
s.Name, errdefs.ErrInvalid)
}
}
if s.MemLimit != 0 && s.Deploy != nil {
if s.Deploy.Resources.Limits != nil && s.Deploy.Resources.Limits.MemoryBytes != s.MemLimit {
return fmt.Errorf("services.%s: can't set distinct values on 'mem_limit' and 'deploy.resources.limits.memory': %w",
s.Name, errdefs.ErrInvalid)
}
}
if s.MemReservation != 0 && s.Deploy != nil {
if s.Deploy.Resources.Reservations != nil && s.Deploy.Resources.Reservations.MemoryBytes != s.MemReservation {
return fmt.Errorf("services.%s: can't set distinct values on 'mem_reservation' and 'deploy.resources.reservations.memory': %w",
s.Name, errdefs.ErrInvalid)
}
}
if s.PidsLimit != 0 && s.Deploy != nil {
if s.Deploy.Resources.Limits != nil && s.Deploy.Resources.Limits.Pids != s.PidsLimit {
return fmt.Errorf("services.%s: can't set distinct values on 'pids_limit' and 'deploy.resources.limits.pids': %w",
s.Name, errdefs.ErrInvalid)
}
}

if s.ContainerName != "" {
if existing, ok := containerNames[s.ContainerName]; ok {
return fmt.Errorf(`"services.%s": container name "%s" is already in use by "services.%s": %w`, s.Name, s.ContainerName, existing, errdefs.ErrInvalid)
Expand Down
27 changes: 26 additions & 1 deletion types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
"sort"
"strconv"
"strings"

"github.com/docker/go-connections/nat"
Expand Down Expand Up @@ -365,7 +366,7 @@ type Resources struct {
// Resource is a resource to be limited or reserved
type Resource struct {
// TODO: types to convert from units and ratios
NanoCPUs string `yaml:"cpus,omitempty" json:"cpus,omitempty"`
NanoCPUs NanoCPUs `yaml:"cpus,omitempty" json:"cpus,omitempty"`
MemoryBytes UnitBytes `yaml:"memory,omitempty" json:"memory,omitempty"`
Pids int64 `yaml:"pids,omitempty" json:"pids,omitempty"`
Devices []DeviceRequest `yaml:"devices,omitempty" json:"devices,omitempty"`
Expand All @@ -374,6 +375,30 @@ type Resource struct {
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
}

type NanoCPUs float32

func (n *NanoCPUs) DecodeMapstructure(a any) error {
switch v := a.(type) {
case string:
f, err := strconv.ParseFloat(v, 64)
if err != nil {
return err
}
*n = NanoCPUs(f)
case float32:
*n = NanoCPUs(v)
case float64:
*n = NanoCPUs(v)
default:
return fmt.Errorf("unexpected value type %T for cpus", v)
}
return nil
}

func (n *NanoCPUs) Value() float32 {
return float32(*n)
}

// GenericResource represents a "user defined" resource which can
// only be an integer (e.g: SSD=3) for a service
type GenericResource struct {
Expand Down

0 comments on commit c37fc59

Please sign in to comment.