Skip to content

Commit 1b45279

Browse files
committed
move ResourceRequirements related functions into /pkg/library/resources/
Signed-off-by: Andrew Obuchowicz <[email protected]>
1 parent 893145a commit 1b45279

File tree

4 files changed

+165
-143
lines changed

4 files changed

+165
-143
lines changed

pkg/library/flatten/helper.go

Lines changed: 0 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ import (
1919
"fmt"
2020
"reflect"
2121

22-
corev1 "k8s.io/api/core/v1"
23-
"k8s.io/apimachinery/pkg/api/resource"
24-
2522
dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
2623
)
2724

@@ -70,97 +67,3 @@ func formatImportCycle(end *resolutionContextTree) string {
7067
}
7168
return cycle
7269
}
73-
74-
func parseResourcesFromComponent(component *dw.Component) (*corev1.ResourceRequirements, error) {
75-
if component.Container == nil {
76-
return nil, fmt.Errorf("attemped to parse resource requirements from a non-container component")
77-
}
78-
79-
resources := &corev1.ResourceRequirements{
80-
Limits: corev1.ResourceList{},
81-
Requests: corev1.ResourceList{},
82-
}
83-
84-
memLimitStr := component.Container.MemoryLimit
85-
if memLimitStr != "" {
86-
memoryLimit, err := resource.ParseQuantity(memLimitStr)
87-
if err != nil {
88-
return nil, fmt.Errorf("failed to parse memory limit for container component %s: %w", component.Name, err)
89-
}
90-
resources.Limits[corev1.ResourceMemory] = memoryLimit
91-
}
92-
93-
memRequestStr := component.Container.MemoryRequest
94-
if memRequestStr != "" {
95-
memoryRequest, err := resource.ParseQuantity(memRequestStr)
96-
if err != nil {
97-
return nil, fmt.Errorf("failed to parse memory request for container component %s: %w", component.Name, err)
98-
}
99-
resources.Requests[corev1.ResourceMemory] = memoryRequest
100-
}
101-
102-
cpuLimitStr := component.Container.CpuLimit
103-
if cpuLimitStr != "" {
104-
cpuLimit, err := resource.ParseQuantity(cpuLimitStr)
105-
if err != nil {
106-
return nil, fmt.Errorf("failed to parse CPU limit for container component %s: %w", component.Name, err)
107-
}
108-
resources.Limits[corev1.ResourceCPU] = cpuLimit
109-
}
110-
111-
cpuRequestStr := component.Container.CpuRequest
112-
if cpuRequestStr != "" {
113-
cpuRequest, err := resource.ParseQuantity(cpuRequestStr)
114-
if err != nil {
115-
return nil, fmt.Errorf("failed to parse CPU request for container component %s: %w", component.Name, err)
116-
}
117-
resources.Requests[corev1.ResourceCPU] = cpuRequest
118-
}
119-
120-
return resources, nil
121-
}
122-
123-
func addResourceRequirements(resources *corev1.ResourceRequirements, toAdd *dw.Component) error {
124-
componentResources, err := parseResourcesFromComponent(toAdd)
125-
if err != nil {
126-
return err
127-
}
128-
129-
for resourceName, limit := range resources.Limits {
130-
if componentLimit, ok := componentResources.Limits[resourceName]; ok {
131-
limit.Add(componentLimit)
132-
resources.Limits[resourceName] = limit
133-
}
134-
}
135-
136-
for resourceName, request := range resources.Requests {
137-
if componentRequest, ok := componentResources.Requests[resourceName]; ok {
138-
request.Add(componentRequest)
139-
resources.Requests[resourceName] = request
140-
}
141-
}
142-
143-
return nil
144-
}
145-
146-
func applyResourceRequirementsToComponent(container *dw.ContainerComponent, resources *corev1.ResourceRequirements) {
147-
memLimit := resources.Limits[corev1.ResourceMemory]
148-
if !memLimit.IsZero() {
149-
container.MemoryLimit = memLimit.String()
150-
}
151-
152-
cpuLimit := resources.Limits[corev1.ResourceCPU]
153-
if !cpuLimit.IsZero() {
154-
container.CpuLimit = cpuLimit.String()
155-
}
156-
157-
memRequest := resources.Requests[corev1.ResourceMemory]
158-
if !memRequest.IsZero() {
159-
container.MemoryRequest = memRequest.String()
160-
}
161-
162-
cpuRequest := resources.Requests[corev1.ResourceCPU]
163-
if !cpuRequest.IsZero() {
164-
container.CpuRequest = cpuRequest.String()
165-
}
166-
}

pkg/library/flatten/merge.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/devfile/api/v2/pkg/attributes"
2525
"github.com/devfile/api/v2/pkg/utils/overriding"
2626
"github.com/devfile/devworkspace-operator/pkg/constants"
27+
dwResources "github.com/devfile/devworkspace-operator/pkg/library/resources"
2728
"k8s.io/apimachinery/pkg/api/resource"
2829
"k8s.io/utils/pointer"
2930
)
@@ -269,7 +270,7 @@ func mergeContributionsInto(mergeInto *dw.Component, contributions []dw.Componen
269270
if mergeInto == nil || mergeInto.Container == nil {
270271
return nil, fmt.Errorf("attempting to merge container contributions into a non-container component")
271272
}
272-
totalResources, err := parseResourcesFromComponent(mergeInto)
273+
totalResources, err := dwResources.ParseResourcesFromComponent(mergeInto)
273274
if err != nil {
274275
return nil, err
275276
}
@@ -293,7 +294,7 @@ func mergeContributionsInto(mergeInto *dw.Component, contributions []dw.Componen
293294
mergedComponentNames = append(mergedComponentNames, component.Attributes.GetString(constants.PluginSourceAttribute, nil))
294295
delete(component.Attributes, constants.PluginSourceAttribute)
295296
}
296-
if err := addResourceRequirements(totalResources, &component); err != nil {
297+
if err := dwResources.AddResourceRequirements(totalResources, &component); err != nil {
297298
return nil, err
298299
}
299300
component.Container.MemoryLimit = ""
@@ -327,7 +328,7 @@ func mergeContributionsInto(mergeInto *dw.Component, contributions []dw.Componen
327328
}
328329

329330
mergedComponent := mergedSpecContent.Components[0]
330-
applyResourceRequirementsToComponent(mergedComponent.Container, totalResources)
331+
dwResources.ApplyResourceRequirementsToComponent(mergedComponent.Container, totalResources)
331332

332333
if mergedComponent.Attributes == nil {
333334
mergedComponent.Attributes = attributes.Attributes{}

pkg/library/projects/clone.go

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@
1717
package projects
1818

1919
import (
20-
"fmt"
21-
2220
dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
2321
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
2422
devfileConstants "github.com/devfile/devworkspace-operator/pkg/library/constants"
2523
"github.com/devfile/devworkspace-operator/pkg/library/env"
24+
dwResources "github.com/devfile/devworkspace-operator/pkg/library/resources"
2625
corev1 "k8s.io/api/core/v1"
2726

2827
"github.com/devfile/devworkspace-operator/internal/images"
@@ -72,7 +71,7 @@ func GetProjectCloneInitContainer(workspace *dw.DevWorkspaceTemplateSpec, option
7271
cloneEnv = append(cloneEnv, env.GetProxyEnvVars(proxyConfig)...)
7372
cloneEnv = append(cloneEnv, options.Env...)
7473

75-
resources, err := processResources(options.Resources)
74+
resources, err := dwResources.ProcessResources(options.Resources)
7675
if err != nil {
7776
return nil, err
7877
}
@@ -92,46 +91,6 @@ func GetProjectCloneInitContainer(workspace *dw.DevWorkspaceTemplateSpec, option
9291
}, nil
9392
}
9493

95-
// processResources checks that specified resources are valid (e.g. requests are less than limits) and supports
96-
// un-setting resources that have default values by interpreting zero as "do not set"
97-
func processResources(resources *corev1.ResourceRequirements) (*corev1.ResourceRequirements, error) {
98-
result := resources.DeepCopy()
99-
100-
if result.Limits.Memory().IsZero() {
101-
delete(result.Limits, corev1.ResourceMemory)
102-
}
103-
if result.Limits.Cpu().IsZero() {
104-
delete(result.Limits, corev1.ResourceCPU)
105-
}
106-
if result.Requests.Memory().IsZero() {
107-
delete(result.Requests, corev1.ResourceMemory)
108-
}
109-
if result.Requests.Cpu().IsZero() {
110-
delete(result.Requests, corev1.ResourceCPU)
111-
}
112-
113-
memLimit, hasMemLimit := result.Limits[corev1.ResourceMemory]
114-
memRequest, hasMemRequest := result.Requests[corev1.ResourceMemory]
115-
if hasMemLimit && hasMemRequest && memRequest.Cmp(memLimit) > 0 {
116-
return result, fmt.Errorf("project clone memory request (%s) must be less than limit (%s)", memRequest.String(), memLimit.String())
117-
}
118-
119-
cpuLimit, hasCPULimit := result.Limits[corev1.ResourceCPU]
120-
cpuRequest, hasCPURequest := result.Requests[corev1.ResourceCPU]
121-
if hasCPULimit && hasCPURequest && cpuRequest.Cmp(cpuLimit) > 0 {
122-
return result, fmt.Errorf("project clone CPU request (%s) must be less than limit (%s)", cpuRequest.String(), cpuLimit.String())
123-
}
124-
125-
if len(result.Limits) == 0 {
126-
result.Limits = nil
127-
}
128-
if len(result.Requests) == 0 {
129-
result.Requests = nil
130-
}
131-
132-
return result, nil
133-
}
134-
13594
func hasContainerComponents(workspace *dw.DevWorkspaceTemplateSpec) bool {
13695
for _, component := range workspace.Components {
13796
if component.Container != nil {

pkg/library/resources/helper.go

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package resources
2+
3+
import (
4+
"fmt"
5+
6+
corev1 "k8s.io/api/core/v1"
7+
"k8s.io/apimachinery/pkg/api/resource"
8+
9+
dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
10+
)
11+
12+
// Takes a component and returns the resource requests and limits that it defines.
13+
// If a resource request or limit is not defined within the component, it will
14+
// not be populated in the corresponding corev1.ResourceList map.
15+
// Returns an error if a non-container component is passed to the function, or if an error
16+
// occurs while parsing a resource limit or request.
17+
func ParseResourcesFromComponent(component *dw.Component) (*corev1.ResourceRequirements, error) {
18+
if component.Container == nil {
19+
return nil, fmt.Errorf("attempted to parse resource requirements from a non-container component")
20+
}
21+
22+
resources := &corev1.ResourceRequirements{
23+
Limits: corev1.ResourceList{},
24+
Requests: corev1.ResourceList{},
25+
}
26+
27+
memLimitStr := component.Container.MemoryLimit
28+
if memLimitStr != "" {
29+
memoryLimit, err := resource.ParseQuantity(memLimitStr)
30+
if err != nil {
31+
return nil, fmt.Errorf("failed to parse memory limit for container component %s: %w", component.Name, err)
32+
}
33+
resources.Limits[corev1.ResourceMemory] = memoryLimit
34+
}
35+
36+
memRequestStr := component.Container.MemoryRequest
37+
if memRequestStr != "" {
38+
memoryRequest, err := resource.ParseQuantity(memRequestStr)
39+
if err != nil {
40+
return nil, fmt.Errorf("failed to parse memory request for container component %s: %w", component.Name, err)
41+
}
42+
resources.Requests[corev1.ResourceMemory] = memoryRequest
43+
}
44+
45+
cpuLimitStr := component.Container.CpuLimit
46+
if cpuLimitStr != "" {
47+
cpuLimit, err := resource.ParseQuantity(cpuLimitStr)
48+
if err != nil {
49+
return nil, fmt.Errorf("failed to parse CPU limit for container component %s: %w", component.Name, err)
50+
}
51+
resources.Limits[corev1.ResourceCPU] = cpuLimit
52+
}
53+
54+
cpuRequestStr := component.Container.CpuRequest
55+
if cpuRequestStr != "" {
56+
cpuRequest, err := resource.ParseQuantity(cpuRequestStr)
57+
if err != nil {
58+
return nil, fmt.Errorf("failed to parse CPU request for container component %s: %w", component.Name, err)
59+
}
60+
resources.Requests[corev1.ResourceCPU] = cpuRequest
61+
}
62+
63+
return resources, nil
64+
}
65+
66+
// Adds the resource limits and requests that are set in the component "toAdd" to "resources".
67+
// Returns an error if the resources defined in toAdd could not be parsed.
68+
//
69+
// Note: only resources that are set in the function argument "resources" will be summed
70+
// with the resources set in "toAdd".
71+
// For example, if "resources" does not set a CPU limit but "toAdd" does set a CPU limit,
72+
// the CPU limit of "resources" will remain unset.
73+
func AddResourceRequirements(resources *corev1.ResourceRequirements, toAdd *dw.Component) error {
74+
componentResources, err := ParseResourcesFromComponent(toAdd)
75+
if err != nil {
76+
return err
77+
}
78+
79+
for resourceName, limit := range resources.Limits {
80+
if componentLimit, ok := componentResources.Limits[resourceName]; ok {
81+
limit.Add(componentLimit)
82+
resources.Limits[resourceName] = limit
83+
}
84+
}
85+
86+
for resourceName, request := range resources.Requests {
87+
if componentRequest, ok := componentResources.Requests[resourceName]; ok {
88+
request.Add(componentRequest)
89+
resources.Requests[resourceName] = request
90+
}
91+
}
92+
93+
return nil
94+
}
95+
96+
// Applies the given resource limits and requirements that are non-zero to the container component.
97+
// If a resource limit or request has a value of zero, then the corresponding limit or request is not set
98+
// in the container component's resource requirements.
99+
func ApplyResourceRequirementsToComponent(container *dw.ContainerComponent, resources *corev1.ResourceRequirements) {
100+
memLimit := resources.Limits[corev1.ResourceMemory]
101+
if !memLimit.IsZero() {
102+
container.MemoryLimit = memLimit.String()
103+
}
104+
105+
cpuLimit := resources.Limits[corev1.ResourceCPU]
106+
if !cpuLimit.IsZero() {
107+
container.CpuLimit = cpuLimit.String()
108+
}
109+
110+
memRequest := resources.Requests[corev1.ResourceMemory]
111+
if !memRequest.IsZero() {
112+
container.MemoryRequest = memRequest.String()
113+
}
114+
115+
cpuRequest := resources.Requests[corev1.ResourceCPU]
116+
if !cpuRequest.IsZero() {
117+
container.CpuRequest = cpuRequest.String()
118+
}
119+
}
120+
121+
// ProcessResources checks that specified resources are valid (e.g. requests are less than limits) and supports
122+
// un-setting resources that have default values by interpreting zero as "do not set"
123+
func ProcessResources(resources *corev1.ResourceRequirements) (*corev1.ResourceRequirements, error) {
124+
result := resources.DeepCopy()
125+
126+
if result.Limits.Memory().IsZero() {
127+
delete(result.Limits, corev1.ResourceMemory)
128+
}
129+
if result.Limits.Cpu().IsZero() {
130+
delete(result.Limits, corev1.ResourceCPU)
131+
}
132+
if result.Requests.Memory().IsZero() {
133+
delete(result.Requests, corev1.ResourceMemory)
134+
}
135+
if result.Requests.Cpu().IsZero() {
136+
delete(result.Requests, corev1.ResourceCPU)
137+
}
138+
139+
memLimit, hasMemLimit := result.Limits[corev1.ResourceMemory]
140+
memRequest, hasMemRequest := result.Requests[corev1.ResourceMemory]
141+
if hasMemLimit && hasMemRequest && memRequest.Cmp(memLimit) > 0 {
142+
return result, fmt.Errorf("project clone memory request (%s) must be less than limit (%s)", memRequest.String(), memLimit.String())
143+
}
144+
145+
cpuLimit, hasCPULimit := result.Limits[corev1.ResourceCPU]
146+
cpuRequest, hasCPURequest := result.Requests[corev1.ResourceCPU]
147+
if hasCPULimit && hasCPURequest && cpuRequest.Cmp(cpuLimit) > 0 {
148+
return result, fmt.Errorf("project clone CPU request (%s) must be less than limit (%s)", cpuRequest.String(), cpuLimit.String())
149+
}
150+
151+
if len(result.Limits) == 0 {
152+
result.Limits = nil
153+
}
154+
if len(result.Requests) == 0 {
155+
result.Requests = nil
156+
}
157+
158+
return result, nil
159+
}

0 commit comments

Comments
 (0)