add validation for PG resources and volume size
This commit is contained in:
		
							parent
							
								
									f9487e41c1
								
							
						
					
					
						commit
						9480b09b2c
					
				|  | @ -227,6 +227,10 @@ func (c *Cluster) Create() error { | |||
| 
 | ||||
| 	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} { | ||||
| 
 | ||||
| 		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
 | ||||
| // (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
 | ||||
|  |  | |||
|  | @ -740,7 +740,7 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef | |||
| 			limit = c.OpConfig.DefaultMemoryLimit | ||||
| 		} | ||||
| 
 | ||||
| 		isSmaller, err := util.RequestIsSmallerThanLimit(request, limit) | ||||
| 		isSmaller, err := util.IsSmallerQuantity(request, limit) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | @ -767,7 +767,7 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef | |||
| 				limit = c.OpConfig.DefaultMemoryLimit | ||||
| 			} | ||||
| 
 | ||||
| 			isSmaller, err := util.RequestIsSmallerThanLimit(sidecarRequest, sidecarLimit) | ||||
| 			isSmaller, err := util.IsSmallerQuantity(sidecarRequest, sidecarLimit) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
|  |  | |||
|  | @ -141,17 +141,17 @@ func Coalesce(val, defaultVal string) string { | |||
| 	return val | ||||
| } | ||||
| 
 | ||||
| // RequestIsSmallerThanLimit : ...
 | ||||
| func RequestIsSmallerThanLimit(requestStr, limitStr string) (bool, error) { | ||||
| // IsSmallerQuantity : checks if first resource is of a smaller quantity than the second
 | ||||
| func IsSmallerQuantity(requestStr, limitStr string) (bool, error) { | ||||
| 
 | ||||
| 	request, err := resource.ParseQuantity(requestStr) | ||||
| 	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) | ||||
| 	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 | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ var substringMatch = []struct { | |||
| 	{regexp.MustCompile(`aaaa (\d+) bbbb`), "aaaa 123 bbbb", nil}, | ||||
| } | ||||
| 
 | ||||
| var requestIsSmallerThanLimitTests = []struct { | ||||
| var requestIsSmallerQuantityTests = []struct { | ||||
| 	request string | ||||
| 	limit   string | ||||
| 	out     bool | ||||
|  | @ -155,9 +155,9 @@ func TestMapContains(t *testing.T) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestRequestIsSmallerThanLimit(t *testing.T) { | ||||
| 	for _, tt := range requestIsSmallerThanLimitTests { | ||||
| 		res, err := RequestIsSmallerThanLimit(tt.request, tt.limit) | ||||
| func TestIsSmallerQuantity(t *testing.T) { | ||||
| 	for _, tt := range requestIsSmallerQuantityTests { | ||||
| 		res, err := IsSmallerQuantity(tt.request, tt.limit) | ||||
| 		if err != nil { | ||||
| 			t.Errorf("RequestIsSmallerThanLimit returned unexpected error: %#v", err) | ||||
| 		} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue