add validation for PG resources and volume size

This commit is contained in:
Felix Kunde 2019-11-21 18:16:46 +01:00
parent f9487e41c1
commit 9480b09b2c
4 changed files with 61 additions and 10 deletions

View File

@ -227,6 +227,10 @@ func (c *Cluster) Create() error {
c.setStatus(acidv1.ClusterStatusCreating) c.setStatus(acidv1.ClusterStatusCreating)
if err = c.validateResources(&c.Spec); err != nil {
return fmt.Errorf("unsufficient ressources: %v", err)
}
for _, role := range []PostgresRole{Master, Replica} { for _, role := range []PostgresRole{Master, Replica} {
if c.Endpoints[role] != nil { if c.Endpoints[role] != nil {
@ -491,6 +495,53 @@ func compareResourcesAssumeFirstNotNil(a *v1.ResourceRequirements, b *v1.Resourc
} }
func (c *Cluster) validateResources(spec *acidv1.PostgresSpec) error {
const (
cpuMinimum = "256m"
memoryMinimum = "256Mi"
storageMinimum = "1Gi"
)
var (
isSmaller bool
err error
)
cpuLimit := spec.Resources.ResourceLimits.CPU
if cpuLimit != "" {
isSmaller, err = util.IsSmallerQuantity(cpuLimit, cpuMinimum)
if err != nil {
return fmt.Errorf("error validating CPU limit: %v", err)
}
if isSmaller {
return fmt.Errorf("defined CPU limit %s is below required minimum %s to properly run postgresql resource", cpuLimit, cpuMinimum)
}
}
memoryLimit := spec.Resources.ResourceLimits.Memory
if memoryLimit != "" {
isSmaller, err = util.IsSmallerQuantity(memoryLimit, memoryMinimum)
if err != nil {
return fmt.Errorf("error validating memory limit: %v", err)
}
if isSmaller {
return fmt.Errorf("defined memory limit %s is below required minimum %s to properly run postgresql resource", memoryLimit, memoryMinimum)
}
}
storageSize := spec.Volume.Size
isSmaller, err = util.IsSmallerQuantity(storageSize, storageMinimum)
if err != nil {
return fmt.Errorf("error validating volume size: %v", err)
}
if isSmaller {
return fmt.Errorf("defined volume size %s is below required minimum %s to properly run postgresql resource", storageSize, storageMinimum)
}
return nil
}
// Update changes Kubernetes objects according to the new specification. Unlike the sync case, the missing object // Update changes Kubernetes objects according to the new specification. Unlike the sync case, the missing object
// (i.e. service) is treated as an error // (i.e. service) is treated as an error
// logical backup cron jobs are an exception: a user-initiated Update can enable a logical backup job // logical backup cron jobs are an exception: a user-initiated Update can enable a logical backup job

View File

@ -740,7 +740,7 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef
limit = c.OpConfig.DefaultMemoryLimit limit = c.OpConfig.DefaultMemoryLimit
} }
isSmaller, err := util.RequestIsSmallerThanLimit(request, limit) isSmaller, err := util.IsSmallerQuantity(request, limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -767,7 +767,7 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef
limit = c.OpConfig.DefaultMemoryLimit limit = c.OpConfig.DefaultMemoryLimit
} }
isSmaller, err := util.RequestIsSmallerThanLimit(sidecarRequest, sidecarLimit) isSmaller, err := util.IsSmallerQuantity(sidecarRequest, sidecarLimit)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -141,17 +141,17 @@ func Coalesce(val, defaultVal string) string {
return val return val
} }
// RequestIsSmallerThanLimit : ... // IsSmallerQuantity : checks if first resource is of a smaller quantity than the second
func RequestIsSmallerThanLimit(requestStr, limitStr string) (bool, error) { func IsSmallerQuantity(requestStr, limitStr string) (bool, error) {
request, err := resource.ParseQuantity(requestStr) request, err := resource.ParseQuantity(requestStr)
if err != nil { if err != nil {
return false, fmt.Errorf("could not parse memory request %v : %v", requestStr, err) return false, fmt.Errorf("could not parse request %v : %v", requestStr, err)
} }
limit, err2 := resource.ParseQuantity(limitStr) limit, err2 := resource.ParseQuantity(limitStr)
if err2 != nil { if err2 != nil {
return false, fmt.Errorf("could not parse memory limit %v : %v", limitStr, err2) return false, fmt.Errorf("could not parse limit %v : %v", limitStr, err2)
} }
return request.Cmp(limit) == -1, nil return request.Cmp(limit) == -1, nil

View File

@ -69,7 +69,7 @@ var substringMatch = []struct {
{regexp.MustCompile(`aaaa (\d+) bbbb`), "aaaa 123 bbbb", nil}, {regexp.MustCompile(`aaaa (\d+) bbbb`), "aaaa 123 bbbb", nil},
} }
var requestIsSmallerThanLimitTests = []struct { var requestIsSmallerQuantityTests = []struct {
request string request string
limit string limit string
out bool out bool
@ -155,9 +155,9 @@ func TestMapContains(t *testing.T) {
} }
} }
func TestRequestIsSmallerThanLimit(t *testing.T) { func TestIsSmallerQuantity(t *testing.T) {
for _, tt := range requestIsSmallerThanLimitTests { for _, tt := range requestIsSmallerQuantityTests {
res, err := RequestIsSmallerThanLimit(tt.request, tt.limit) res, err := IsSmallerQuantity(tt.request, tt.limit)
if err != nil { if err != nil {
t.Errorf("RequestIsSmallerThanLimit returned unexpected error: %#v", err) t.Errorf("RequestIsSmallerThanLimit returned unexpected error: %#v", err)
} }