feat: Set empty CPU limits when possible (#1686)

* feat: Set empty CPU limits when possible

Signed-off-by: Anatolii Bazko <abazko@redhat.com>
pull/1689/head
Anatolii Bazko 2023-05-25 17:20:44 +03:00 committed by GitHub
parent b31b92b137
commit 97f6177500
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 327 additions and 117 deletions

View File

@ -77,7 +77,7 @@ metadata:
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3
repository: https://github.com/eclipse-che/che-operator
support: Eclipse Foundation
name: eclipse-che.v7.68.0-793.next
name: eclipse-che.v7.68.0-794.next
namespace: placeholder
spec:
apiservicedefinitions: {}
@ -866,6 +866,12 @@ spec:
- delete
- update
- use
- apiGroups:
- ""
resources:
- limitranges
verbs:
- list
serviceAccountName: che-operator
deployments:
- name: che-operator
@ -1229,7 +1235,7 @@ spec:
minKubeVersion: 1.19.0
provider:
name: Eclipse Foundation
version: 7.68.0-793.next
version: 7.68.0-794.next
webhookdefinitions:
- admissionReviewVersions:
- v1

View File

@ -402,4 +402,10 @@ rules:
- create
- delete
- update
- use
- use
- apiGroups:
- ""
resources:
- limitranges
verbs:
- list

View File

@ -199,10 +199,8 @@ func (c *CheRoutingSolver) provisionPodAdditions(objs *solvers.RoutingObjects, c
},
}
if cheCluster.Spec.DevEnvironments.GatewayContainer != nil {
if err := deploy.CustomizeContainer(gatewayContainer, cheCluster.Spec.DevEnvironments.GatewayContainer); err != nil {
return err
}
if err := deploy.OverrideContainer(routing.GetNamespace(), gatewayContainer, cheCluster.Spec.DevEnvironments.GatewayContainer); err != nil {
return err
}
objs.PodAdditions.Containers = append(objs.PodAdditions.Containers, *gatewayContainer)

View File

@ -20,8 +20,6 @@ import (
"github.com/stretchr/testify/assert"
// "k8s.io/apimachinery/pkg/api/resource"
dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
dwo "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
"github.com/devfile/devworkspace-operator/controllers/controller/devworkspacerouting/solvers"
@ -1094,7 +1092,8 @@ func TestOverrideGatewayContainerProvisioning(t *testing.T) {
},
}
cheSolver.provisionPodAdditions(objs, cheCluster, routing)
err := cheSolver.provisionPodAdditions(objs, cheCluster, routing)
assert.NoError(t, err)
assert.Equal(t, overrideCpuRequest.String(), objs.PodAdditions.Containers[0].Resources.Requests.Cpu().String())
assert.Equal(t, overrideMemoryRequest.String(), objs.PodAdditions.Containers[0].Resources.Requests.Memory().String())
@ -1106,7 +1105,6 @@ func TestOverridePartialLimitsGatewayContainerProvisioning(t *testing.T) {
overrideMemoryRequest := resource.MustParse("0")
overrideCpuRequest := resource.MustParse("0")
defaultMemoryLimit := resource.MustParse(constants.DefaultGatewayMemoryLimit)
defaultCpuLimit := resource.MustParse(constants.DefaultGatewayCpuLimit)
cheCluster := &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
@ -1147,11 +1145,12 @@ func TestOverridePartialLimitsGatewayContainerProvisioning(t *testing.T) {
},
}
cheSolver.provisionPodAdditions(objs, cheCluster, routing)
err := cheSolver.provisionPodAdditions(objs, cheCluster, routing)
assert.NoError(t, err)
assert.Equal(t, overrideCpuRequest.String(), objs.PodAdditions.Containers[0].Resources.Requests.Cpu().String())
assert.Equal(t, overrideMemoryRequest.String(), objs.PodAdditions.Containers[0].Resources.Requests.Memory().String())
assert.Equal(t, defaultCpuLimit.String(), objs.PodAdditions.Containers[0].Resources.Limits.Cpu().String())
assert.Empty(t, objs.PodAdditions.Containers[0].Resources.Limits[corev1.ResourceCPU])
assert.Equal(t, defaultMemoryLimit.String(), objs.PodAdditions.Containers[0].Resources.Limits.Memory().String())
}
@ -1204,7 +1203,8 @@ func TestOverrideGatewayEmptyContainerProvisioning(t *testing.T) {
},
}
cheSolver.provisionPodAdditions(objs, cheCluster, routing)
err := cheSolver.provisionPodAdditions(objs, cheCluster, routing)
assert.NoError(t, err)
assert.Equal(t, overrideCpuRequest.String(), objs.PodAdditions.Containers[0].Resources.Requests.Cpu().String())
assert.Equal(t, overrideMemoryRequest.String(), objs.PodAdditions.Containers[0].Resources.Requests.Memory().String())
@ -1216,7 +1216,6 @@ func TestDefaultGatewayContainerProvisioning(t *testing.T) {
defaultMemoryRequest := resource.MustParse(constants.DefaultGatewayMemoryRequest)
defaultCpuRequest := resource.MustParse(constants.DefaultGatewayCpuRequest)
defaultMemoryLimit := resource.MustParse(constants.DefaultGatewayMemoryLimit)
defaultCpuLimit := resource.MustParse(constants.DefaultGatewayCpuLimit)
cheCluster := &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
@ -1247,10 +1246,11 @@ func TestDefaultGatewayContainerProvisioning(t *testing.T) {
},
}
cheSolver.provisionPodAdditions(objs, cheCluster, routing)
err := cheSolver.provisionPodAdditions(objs, cheCluster, routing)
assert.NoError(t, err)
assert.Equal(t, defaultCpuRequest.String(), objs.PodAdditions.Containers[0].Resources.Requests.Cpu().String())
assert.Equal(t, defaultMemoryRequest.String(), objs.PodAdditions.Containers[0].Resources.Requests.Memory().String())
assert.Equal(t, defaultCpuLimit.String(), objs.PodAdditions.Containers[0].Resources.Limits.Cpu().String())
assert.Empty(t, objs.PodAdditions.Containers[0].Resources.Limits[corev1.ResourceCPU])
assert.Equal(t, defaultMemoryLimit.String(), objs.PodAdditions.Containers[0].Resources.Limits.Memory().String())
}

View File

@ -8123,6 +8123,12 @@ rules:
- delete
- update
- use
- apiGroups:
- ""
resources:
- limitranges
verbs:
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding

View File

@ -403,3 +403,9 @@ rules:
- delete
- update
- use
- apiGroups:
- ""
resources:
- limitranges
verbs:
- list

View File

@ -8123,6 +8123,12 @@ rules:
- delete
- update
- use
- apiGroups:
- ""
resources:
- limitranges
verbs:
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding

View File

@ -403,3 +403,9 @@ rules:
- delete
- update
- use
- apiGroups:
- ""
resources:
- limitranges
verbs:
- list

View File

@ -403,3 +403,9 @@ rules:
- delete
- update
- use
- apiGroups:
- ""
resources:
- limitranges
verbs:
- list

View File

@ -71,7 +71,7 @@ func TestDashboardDeploymentResources(t *testing.T) {
initObjects: []runtime.Object{},
memoryLimit: constants.DefaultDashboardMemoryLimit,
memoryRequest: constants.DefaultDashboardMemoryRequest,
cpuLimit: constants.DefaultDashboardCpuLimit,
cpuLimit: "0", // CPU limit is not set when possible
cpuRequest: constants.DefaultDashboardCpuRequest,
cheCluster: &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{

View File

@ -197,7 +197,9 @@ func (d *DashboardReconciler) getDashboardDeploymentSpec(ctx *chetypes.DeployCon
}
deploy.EnsurePodSecurityStandards(deployment, constants.DefaultSecurityContextRunAsUser, constants.DefaultSecurityContextFsGroup)
deploy.CustomizeDeployment(deployment, ctx.CheCluster.Spec.Components.Dashboard.Deployment)
if err := deploy.OverrideDeployment(ctx, deployment, ctx.CheCluster.Spec.Components.Dashboard.Deployment); err != nil {
return nil, err
}
return deployment, nil
}

View File

@ -17,6 +17,9 @@ import (
"sort"
"strings"
k8shelper "github.com/eclipse-che/che-operator/pkg/common/k8s-helper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/utils/pointer"
@ -96,39 +99,47 @@ func SyncDeploymentSpecToCluster(
return provisioned, nil
}
// CustomizeDeployment customize deployment
func CustomizeDeployment(deployment *appsv1.Deployment, customSettings *chev2.Deployment) error {
if customSettings == nil || len(customSettings.Containers) == 0 {
return nil
}
// OverrideDeployment with custom settings
func OverrideDeployment(
ctx *chetypes.DeployContext,
deployment *appsv1.Deployment,
overrideDeploymentSettings *chev2.Deployment) error {
for index, _ := range deployment.Spec.Template.Spec.Containers {
var overrideContainerSettings *chev2.Container
container := &deployment.Spec.Template.Spec.Containers[index]
customContainer := &customSettings.Containers[0]
if len(deployment.Spec.Template.Spec.Containers) != 1 {
customContainer = getContainerByName(container.Name, customSettings.Containers)
if customContainer == nil {
continue
if overrideDeploymentSettings != nil {
if len(deployment.Spec.Template.Spec.Containers) != 1 {
for _, c := range overrideDeploymentSettings.Containers {
if c.Name == container.Name {
overrideContainerSettings = &c
break
}
}
} else {
overrideContainerSettings = &overrideDeploymentSettings.Containers[0]
}
}
if err := CustomizeContainer(container, customContainer); err != nil {
if err := OverrideContainer(ctx.CheCluster.Namespace, container, overrideContainerSettings); err != nil {
return err
}
}
if !infrastructure.IsOpenShift() {
if customSettings.SecurityContext != nil {
if deployment.Spec.Template.Spec.SecurityContext == nil {
deployment.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{}
}
if overrideDeploymentSettings != nil {
if overrideDeploymentSettings.SecurityContext != nil {
if deployment.Spec.Template.Spec.SecurityContext == nil {
deployment.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{}
}
if customSettings.SecurityContext.FsGroup != nil {
deployment.Spec.Template.Spec.SecurityContext.FSGroup = pointer.Int64Ptr(*customSettings.SecurityContext.FsGroup)
}
if customSettings.SecurityContext.RunAsUser != nil {
deployment.Spec.Template.Spec.SecurityContext.RunAsUser = pointer.Int64Ptr(*customSettings.SecurityContext.RunAsUser)
if overrideDeploymentSettings.SecurityContext.FsGroup != nil {
deployment.Spec.Template.Spec.SecurityContext.FSGroup = pointer.Int64Ptr(*overrideDeploymentSettings.SecurityContext.FsGroup)
}
if overrideDeploymentSettings.SecurityContext.RunAsUser != nil {
deployment.Spec.Template.Spec.SecurityContext.RunAsUser = pointer.Int64Ptr(*overrideDeploymentSettings.SecurityContext.RunAsUser)
}
}
}
}
@ -136,16 +147,37 @@ func CustomizeDeployment(deployment *appsv1.Deployment, customSettings *chev2.De
return nil
}
// CustomizeContainer customize container with custom settings.
func CustomizeContainer(container *corev1.Container, customSettings *chev2.Container) error {
container.Image = utils.GetValue(customSettings.Image, container.Image)
func OverrideContainer(
namespace string,
container *corev1.Container,
overrideSettings *chev2.Container) error {
container.ImagePullPolicy = customSettings.ImagePullPolicy
// Set empty CPU limits when possible:
// 1. If there is no LimitRange in the namespace
// 2. CPU limits is not overridden
// See details at https://github.com/eclipse/che/issues/22198
if overrideSettings == nil || overrideSettings.Resources == nil || overrideSettings.Resources.Limits == nil || overrideSettings.Resources.Limits.Cpu == nil {
// use NonCachedClient to avoid cache LimitRange objects
if limitRanges, err := k8shelper.New().GetClientset().CoreV1().LimitRanges(namespace).List(context.TODO(), metav1.ListOptions{}); err != nil {
return err
} else if len(limitRanges.Items) == 0 { // no LimitRange in the namespace
delete(container.Resources.Limits, corev1.ResourceCPU)
}
}
if overrideSettings == nil {
return nil
}
// Image
container.Image = utils.GetValue(overrideSettings.Image, container.Image)
container.ImagePullPolicy = overrideSettings.ImagePullPolicy
if container.ImagePullPolicy == "" {
container.ImagePullPolicy = corev1.PullPolicy(utils.GetPullPolicyFromDockerImage(container.Image))
}
for _, env := range customSettings.Env {
// Env
for _, env := range overrideSettings.Env {
index := utils.IndexEnv(env.Name, container.Env)
if index == -1 {
container.Env = append(container.Env, env)
@ -154,21 +186,22 @@ func CustomizeContainer(container *corev1.Container, customSettings *chev2.Conta
}
}
if customSettings.Resources != nil {
if customSettings.Resources.Requests != nil {
if customSettings.Resources.Requests.Memory != nil {
if customSettings.Resources.Requests.Memory.IsZero() {
// Resources
if overrideSettings.Resources != nil {
if overrideSettings.Resources.Requests != nil {
if overrideSettings.Resources.Requests.Memory != nil {
if overrideSettings.Resources.Requests.Memory.IsZero() {
delete(container.Resources.Requests, corev1.ResourceMemory)
} else {
container.Resources.Requests[corev1.ResourceMemory] = *customSettings.Resources.Requests.Memory
container.Resources.Requests[corev1.ResourceMemory] = *overrideSettings.Resources.Requests.Memory
}
}
if customSettings.Resources.Requests.Cpu != nil {
if customSettings.Resources.Requests.Cpu.IsZero() {
if overrideSettings.Resources.Requests.Cpu != nil {
if overrideSettings.Resources.Requests.Cpu.IsZero() {
delete(container.Resources.Requests, corev1.ResourceCPU)
} else {
container.Resources.Requests[corev1.ResourceCPU] = *customSettings.Resources.Requests.Cpu
container.Resources.Requests[corev1.ResourceCPU] = *overrideSettings.Resources.Requests.Cpu
}
}
@ -177,20 +210,20 @@ func CustomizeContainer(container *corev1.Container, customSettings *chev2.Conta
}
}
if customSettings.Resources.Limits != nil {
if customSettings.Resources.Limits.Memory != nil {
if customSettings.Resources.Limits.Memory.IsZero() {
if overrideSettings.Resources.Limits != nil {
if overrideSettings.Resources.Limits.Memory != nil {
if overrideSettings.Resources.Limits.Memory.IsZero() {
delete(container.Resources.Limits, corev1.ResourceMemory)
} else {
container.Resources.Limits[corev1.ResourceMemory] = *customSettings.Resources.Limits.Memory
container.Resources.Limits[corev1.ResourceMemory] = *overrideSettings.Resources.Limits.Memory
}
}
if customSettings.Resources.Limits.Cpu != nil {
if customSettings.Resources.Limits.Cpu.IsZero() {
if overrideSettings.Resources.Limits.Cpu != nil {
if overrideSettings.Resources.Limits.Cpu.IsZero() {
delete(container.Resources.Limits, corev1.ResourceCPU)
} else {
container.Resources.Limits[corev1.ResourceCPU] = *customSettings.Resources.Limits.Cpu
container.Resources.Limits[corev1.ResourceCPU] = *overrideSettings.Resources.Limits.Cpu
}
}
@ -223,16 +256,6 @@ func EnsurePodSecurityStandards(deployment *appsv1.Deployment, userId int64, gro
}
}
func getContainerByName(name string, containers []chev2.Container) *chev2.Container {
for _, c := range containers {
if c.Name == name {
return &c
}
}
return nil
}
// MountSecrets mounts secrets into a container as a file or as environment variable.
// Secrets are selected by the following labels:
// - app.kubernetes.io/part-of=che.eclipse.org

View File

@ -16,6 +16,10 @@ import (
"os"
"reflect"
k8shelper "github.com/eclipse-che/che-operator/pkg/common/k8s-helper"
"github.com/eclipse-che/che-operator/pkg/common/test"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/api/resource"
@ -707,11 +711,14 @@ func TestCustomizeDeploymentShouldNotUpdateResources(t *testing.T) {
},
}
err := CustomizeDeployment(deployment, customizationDeployment)
ctx := test.GetDeployContext(nil, []runtime.Object{})
err := OverrideDeployment(ctx, deployment, customizationDeployment)
assert.Nil(t, err)
assert.Equal(t, "1", deployment.Spec.Template.Spec.Containers[0].Resources.Requests.Cpu().String())
assert.Equal(t, "100Mi", deployment.Spec.Template.Spec.Containers[0].Resources.Requests.Memory().String())
assert.Equal(t, "2", deployment.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().String())
// CPU limit is not set when possible
assert.Equal(t, "0", deployment.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().String())
assert.Equal(t, "200Mi", deployment.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().String())
}
@ -790,8 +797,10 @@ func TestCustomizeDeploymentImagePullPolicy(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true)))
err := CustomizeDeployment(testCase.initDeployment, testCase.customizationDeployment)
ctx := test.GetDeployContext(nil, []runtime.Object{})
err := OverrideDeployment(ctx, testCase.initDeployment, testCase.customizationDeployment)
assert.Nil(t, err)
assert.Equal(t, testCase.expectedImagePullPolicy, testCase.initDeployment.Spec.Template.Spec.Containers[0].ImagePullPolicy)
})
}
@ -873,9 +882,136 @@ func TestCustomizeDeploymentEnvVar(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true)))
err := CustomizeDeployment(testCase.initDeployment, testCase.customizationDeployment)
ctx := test.GetDeployContext(nil, []runtime.Object{})
err := OverrideDeployment(ctx, testCase.initDeployment, testCase.customizationDeployment)
assert.Nil(t, err)
assert.Equal(t, testCase.expectedEnv, testCase.initDeployment.Spec.Template.Spec.Containers[0].Env)
})
}
}
func TestOverrideContainerCpuLimit(t *testing.T) {
type testCase struct {
name string
container *corev1.Container
overrideSettings *chev2.Container
limitRange *corev1.LimitRange
expectedCpuLimit string
}
cpuLimit500m := resource.MustParse("500m")
testCases := []testCase{
{
name: "No CPU limit, LimitRange does not exists",
container: &corev1.Container{
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("250m"),
},
},
},
overrideSettings: &chev2.Container{},
expectedCpuLimit: "",
},
{
name: "No CPU limit, LimitRange does not exists",
container: &corev1.Container{
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("250m"),
},
},
},
overrideSettings: nil,
expectedCpuLimit: "",
},
{
name: "CPU limit is set, LimitRange exists",
container: &corev1.Container{
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("250m"),
},
},
},
overrideSettings: &chev2.Container{},
limitRange: &corev1.LimitRange{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "eclipse-che",
},
},
expectedCpuLimit: "250m",
},
{
name: "Overridden CPU limit, LimitRange does not exists",
container: &corev1.Container{
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("250m"),
},
},
},
overrideSettings: &chev2.Container{
Resources: &chev2.ResourceRequirements{
Limits: &chev2.ResourceList{
Cpu: &cpuLimit500m,
},
},
},
expectedCpuLimit: "500m",
},
{
name: "Overridden CPU limit, LimitRange exists",
container: &corev1.Container{
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("250m"),
},
},
},
overrideSettings: &chev2.Container{
Resources: &chev2.ResourceRequirements{
Limits: &chev2.ResourceList{
Cpu: &cpuLimit500m,
},
},
},
limitRange: &corev1.LimitRange{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "eclipse-che",
},
},
expectedCpuLimit: "500m",
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
k8sHelper := k8shelper.New()
if testCase.limitRange != nil {
_, err := k8sHelper.GetClientset().CoreV1().LimitRanges("eclipse-che").Create(context.TODO(), testCase.limitRange, metav1.CreateOptions{})
assert.NoError(t, err)
}
err := OverrideContainer("eclipse-che", testCase.container, testCase.overrideSettings)
assert.NoError(t, err)
if testCase.expectedCpuLimit == "" {
assert.Empty(t, testCase.container.Resources.Limits[corev1.ResourceCPU])
} else {
assert.Equal(t, testCase.expectedCpuLimit, testCase.container.Resources.Limits.Cpu().String())
}
defer func() {
if testCase.limitRange != nil {
err := k8sHelper.GetClientset().CoreV1().LimitRanges("eclipse-che").Delete(context.TODO(), testCase.limitRange.Name, metav1.DeleteOptions{})
assert.NoError(t, err)
}
}()
})
}
}

View File

@ -106,8 +106,11 @@ func (d *DevfileRegistryReconciler) updateStatus(endpoint string, ctx *chetypes.
}
func (d *DevfileRegistryReconciler) syncDeployment(ctx *chetypes.DeployContext) (bool, error) {
spec := d.getDevfileRegistryDeploymentSpec(ctx)
return deploy.SyncDeploymentSpecToCluster(ctx, spec, deploy.DefaultDeploymentDiffOpts)
if spec, err := d.getDevfileRegistryDeploymentSpec(ctx); err != nil {
return false, err
} else {
return deploy.SyncDeploymentSpecToCluster(ctx, spec, deploy.DefaultDeploymentDiffOpts)
}
}
func (d *DevfileRegistryReconciler) createGatewayConfig() *gateway.TraefikConfig {

View File

@ -23,7 +23,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
)
func (d *DevfileRegistryReconciler) getDevfileRegistryDeploymentSpec(ctx *chetypes.DeployContext) *appsv1.Deployment {
func (d *DevfileRegistryReconciler) getDevfileRegistryDeploymentSpec(ctx *chetypes.DeployContext) (*appsv1.Deployment, error) {
registryType := "devfile"
registryImage := defaults.GetDevfileRegistryImage(ctx.CheCluster)
registryImagePullPolicy := v1.PullPolicy(utils.GetPullPolicyFromDockerImage(registryImage))
@ -51,6 +51,8 @@ func (d *DevfileRegistryReconciler) getDevfileRegistryDeploymentSpec(ctx *chetyp
probePath)
deploy.EnsurePodSecurityStandards(deployment, constants.DefaultSecurityContextRunAsUser, constants.DefaultSecurityContextFsGroup)
deploy.CustomizeDeployment(deployment, ctx.CheCluster.Spec.Components.DevfileRegistry.Deployment)
return deployment
if err := deploy.OverrideDeployment(ctx, deployment, ctx.CheCluster.Spec.Components.DevfileRegistry.Deployment); err != nil {
return nil, err
}
return deployment, nil
}

View File

@ -14,6 +14,8 @@ package devfileregistry
import (
"os"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/api/resource"
"github.com/eclipse-che/che-operator/pkg/common/constants"
@ -50,7 +52,7 @@ func TestGetDevfileRegistryDeploymentSpec(t *testing.T) {
initObjects: []runtime.Object{},
memoryLimit: constants.DefaultDevfileRegistryMemoryLimit,
memoryRequest: constants.DefaultDevfileRegistryMemoryRequest,
cpuLimit: constants.DefaultDevfileRegistryCpuLimit,
cpuLimit: "0", // CPU limit is not set when possible
cpuRequest: constants.DefaultDevfileRegistryCpuRequest,
cheCluster: &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
@ -104,7 +106,8 @@ func TestGetDevfileRegistryDeploymentSpec(t *testing.T) {
ctx := test.GetDeployContext(testCase.cheCluster, []runtime.Object{})
devfileregistry := NewDevfileRegistryReconciler()
deployment := devfileregistry.getDevfileRegistryDeploymentSpec(ctx)
deployment, err := devfileregistry.getDevfileRegistryDeploymentSpec(ctx)
assert.NoError(t, err)
test.CompareResources(deployment,
test.TestExpectedResources{

View File

@ -142,7 +142,10 @@ func syncAll(deployContext *chetypes.DeployContext) error {
return err
}
depl := getGatewayDeploymentSpec(deployContext)
depl, err := getGatewayDeploymentSpec(deployContext)
if err != nil {
return err
}
if _, err := deploy.Sync(deployContext, depl, deploy.DefaultDeploymentDiffOpts); err != nil {
// Failed to sync (update), let's delete and create instead
if strings.Contains(err.Error(), "field is immutable") {
@ -424,7 +427,7 @@ experimental:
}
}
func getGatewayDeploymentSpec(ctx *chetypes.DeployContext) *appsv1.Deployment {
func getGatewayDeploymentSpec(ctx *chetypes.DeployContext) (*appsv1.Deployment, error) {
terminationGracePeriodSeconds := int64(10)
deployLabels, labelsSelector := deploy.GetLabelsAndSelector(GatewayServiceName)
@ -462,8 +465,11 @@ func getGatewayDeploymentSpec(ctx *chetypes.DeployContext) *appsv1.Deployment {
}
deploy.EnsurePodSecurityStandards(deployment, constants.DefaultSecurityContextRunAsUser, constants.DefaultSecurityContextFsGroup)
deploy.CustomizeDeployment(deployment, ctx.CheCluster.Spec.Networking.Auth.Gateway.Deployment)
return deployment
if err := deploy.OverrideDeployment(ctx, deployment, ctx.CheCluster.Spec.Networking.Auth.Gateway.Deployment); err != nil {
return nil, err
}
return deployment, nil
}
func getContainersSpec(ctx *chetypes.DeployContext) []corev1.Container {

View File

@ -304,7 +304,8 @@ func TestCustomizeGatewayDeploymentAllImages(t *testing.T) {
}
ctx := test.GetDeployContext(checluster, []runtime.Object{})
deployment := getGatewayDeploymentSpec(ctx)
deployment, err := getGatewayDeploymentSpec(ctx)
assert.NoError(t, err)
containers := deployment.Spec.Template.Spec.Containers
assert.Equal(t, constants.GatewayContainerName, containers[0].Name)
assert.Equal(t, "gateway-image", containers[0].Image)
@ -344,7 +345,9 @@ func TestCustomizeGatewayDeploymentSingleImage(t *testing.T) {
}
ctx := test.GetDeployContext(checluster, []runtime.Object{})
deployment := getGatewayDeploymentSpec(ctx)
deployment, err := getGatewayDeploymentSpec(ctx)
assert.NoError(t, err)
containers := deployment.Spec.Template.Spec.Containers
assert.Equal(t, constants.GatewayContainerName, containers[0].Name)
assert.Equal(t, "gateway-image", containers[0].Image)

View File

@ -116,8 +116,11 @@ func (p *PluginRegistryReconciler) updateStatus(endpoint string, ctx *chetypes.D
}
func (p *PluginRegistryReconciler) syncDeployment(ctx *chetypes.DeployContext) (bool, error) {
spec := p.getPluginRegistryDeploymentSpec(ctx)
return deploy.SyncDeploymentSpecToCluster(ctx, spec, deploy.DefaultDeploymentDiffOpts)
if spec, err := p.getPluginRegistryDeploymentSpec(ctx); err != nil {
return false, err
} else {
return deploy.SyncDeploymentSpecToCluster(ctx, spec, deploy.DefaultDeploymentDiffOpts)
}
}
func (p *PluginRegistryReconciler) createGatewayConfig(ctx *chetypes.DeployContext) *gateway.TraefikConfig {

View File

@ -23,7 +23,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
)
func (p *PluginRegistryReconciler) getPluginRegistryDeploymentSpec(ctx *chetypes.DeployContext) *appsv1.Deployment {
func (p *PluginRegistryReconciler) getPluginRegistryDeploymentSpec(ctx *chetypes.DeployContext) (*appsv1.Deployment, error) {
registryType := "plugin"
registryImage := defaults.GetPluginRegistryImage(ctx.CheCluster)
registryImagePullPolicy := corev1.PullPolicy(utils.GetPullPolicyFromDockerImage(registryImage))
@ -62,6 +62,9 @@ func (p *PluginRegistryReconciler) getPluginRegistryDeploymentSpec(ctx *chetypes
}
deploy.EnsurePodSecurityStandards(deployment, constants.DefaultSecurityContextRunAsUser, constants.DefaultSecurityContextFsGroup)
deploy.CustomizeDeployment(deployment, ctx.CheCluster.Spec.Components.PluginRegistry.Deployment)
return deployment
if err := deploy.OverrideDeployment(ctx, deployment, ctx.CheCluster.Spec.Components.PluginRegistry.Deployment); err != nil {
return nil, err
}
return deployment, nil
}

View File

@ -14,6 +14,7 @@ package pluginregistry
import (
"github.com/eclipse-che/che-operator/pkg/common/constants"
"github.com/eclipse-che/che-operator/pkg/common/test"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/utils/pointer"
@ -46,7 +47,7 @@ func TestGetPluginRegistryDeploymentSpec(t *testing.T) {
initObjects: []runtime.Object{},
memoryLimit: constants.DefaultPluginRegistryMemoryLimitEmbeddedOpenVSXRegistry,
memoryRequest: constants.DefaultPluginRegistryMemoryRequestEmbeddedOpenVSXRegistry,
cpuLimit: constants.DefaultPluginRegistryCpuLimit,
cpuLimit: "0", // CPU limit is not set when possible
cpuRequest: constants.DefaultPluginRegistryCpuRequest,
cheCluster: &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
@ -67,7 +68,7 @@ func TestGetPluginRegistryDeploymentSpec(t *testing.T) {
initObjects: []runtime.Object{},
memoryLimit: constants.DefaultPluginRegistryMemoryLimit,
memoryRequest: constants.DefaultPluginRegistryMemoryRequest,
cpuLimit: constants.DefaultPluginRegistryCpuLimit,
cpuLimit: "0", // CPU limit is not set when possible
cpuRequest: constants.DefaultPluginRegistryCpuRequest,
cheCluster: &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
@ -127,7 +128,8 @@ func TestGetPluginRegistryDeploymentSpec(t *testing.T) {
ctx := test.GetDeployContext(testCase.cheCluster, []runtime.Object{})
pluginregistry := NewPluginRegistryReconciler()
deployment := pluginregistry.getPluginRegistryDeploymentSpec(ctx)
deployment, err := pluginregistry.getPluginRegistryDeploymentSpec(ctx)
assert.NoError(t, err)
test.CompareResources(deployment,
test.TestExpectedResources{

View File

@ -271,7 +271,9 @@ func (s CheServerReconciler) getDeploymentSpec(ctx *chetypes.DeployContext) (*ap
}
deploy.EnsurePodSecurityStandards(deployment, constants.DefaultSecurityContextRunAsUser, constants.DefaultSecurityContextFsGroup)
deploy.CustomizeDeployment(deployment, ctx.CheCluster.Spec.Components.CheServer.Deployment)
if err := deploy.OverrideDeployment(ctx, deployment, ctx.CheCluster.Spec.Components.CheServer.Deployment); err != nil {
return nil, err
}
return deployment, nil
}

View File

@ -12,27 +12,20 @@
package server
import (
"os"
"k8s.io/apimachinery/pkg/api/resource"
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
"github.com/eclipse-che/che-operator/pkg/common/constants"
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
"github.com/eclipse-che/che-operator/pkg/common/test"
"github.com/eclipse-che/che-operator/pkg/common/utils"
"github.com/stretchr/testify/assert"
"testing"
chev2 "github.com/eclipse-che/che-operator/api/v2"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"testing"
)
func TestDeployment(t *testing.T) {
@ -57,7 +50,7 @@ func TestDeployment(t *testing.T) {
initObjects: []runtime.Object{},
memoryLimit: constants.DefaultServerMemoryLimit,
memoryRequest: constants.DefaultServerMemoryRequest,
cpuLimit: constants.DefaultServerCpuLimit,
cpuLimit: "0", // no CPU limit if LimitRange does not exists
cpuRequest: constants.DefaultServerCpuRequest,
cheCluster: &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
@ -105,18 +98,7 @@ func TestDeployment(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true)))
chev2.SchemeBuilder.AddToScheme(scheme.Scheme)
testCase.initObjects = append(testCase.initObjects)
cli := fake.NewFakeClientWithScheme(scheme.Scheme, testCase.initObjects...)
ctx := &chetypes.DeployContext{
CheCluster: testCase.cheCluster,
ClusterAPI: chetypes.ClusterAPI{
Client: cli,
Scheme: scheme.Scheme,
},
}
ctx := test.GetDeployContext(testCase.cheCluster, testCase.initObjects)
server := NewCheServerReconciler()
deployment, err := server.getDeploymentSpec(ctx)