Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions pkg/controller/certmanager/deployment_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ package certmanager
import (
"fmt"
"sort"
"unsafe"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/util/tolerations"

"github.com/openshift/cert-manager-operator/api/operator/v1alpha1"
"github.com/openshift/cert-manager-operator/pkg/controller/common"
certmanagerinformer "github.com/openshift/cert-manager-operator/pkg/operator/informers/externalversions/operator/v1alpha1"
)

Expand Down Expand Up @@ -75,15 +74,11 @@ func mergePodScheduling(sourceScheduling v1alpha1.CertManagerScheduling, overrid
// Merge the source and override NodeSelector.
mergedNodeSelector := labels.Merge(sourceScheduling.NodeSelector, overrideScheduling.NodeSelector)

// Convert corev1.Tolerations to core.Tolerations.
sourceTolerations := *(*[]core.Toleration)(unsafe.Pointer(&sourceScheduling.Tolerations))
overridingTolerations := *(*[]core.Toleration)(unsafe.Pointer(&overrideScheduling.Tolerations))

// Merge the source and override Tolerations.
mergedCoreTolerations := tolerations.MergeTolerations(sourceTolerations, overridingTolerations)

// Convert core.Tolerations to corev1.Tolerations.
mergedCorev1Tolerations := *(*[]corev1.Toleration)(unsafe.Pointer(&mergedCoreTolerations))
mergedCoreTolerations := tolerations.MergeTolerations(
common.ToCoreTolerations(sourceScheduling.Tolerations),
common.ToCoreTolerations(overrideScheduling.Tolerations),
)
mergedCorev1Tolerations := common.ToV1Tolerations(mergedCoreTolerations)

return v1alpha1.CertManagerScheduling{
NodeSelector: mergedNodeSelector,
Expand Down
294 changes: 291 additions & 3 deletions pkg/controller/certmanager/deployment_helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ func TestGetOverrideResourcesFor(t *testing.T) {
withFakeCertManagerForTest(t, ctx, fakeClient, certManagerChan, &tc.certManagerObj)

actualOverrideResources, err := getOverrideResourcesFor(certManagerInformers, tc.deploymentName)
assert.NoError(t, err)
require.NoError(t, err)
require.Equal(t, tc.expectedOverrideResources, actualOverrideResources)
})
}
Expand Down Expand Up @@ -872,12 +872,300 @@ func TestGetOverrideSchedulingFor(t *testing.T) {
withFakeCertManagerForTest(t, ctx, fakeClient, certManagerChan, &tc.certManagerObj)

actualOverrideScheduling, err := getOverrideSchedulingFor(certManagerInformers, tc.deploymentName)
assert.NoError(t, err)
require.NoError(t, err)
require.Equal(t, tc.expectedOverrideScheduling, actualOverrideScheduling)
})
}
}

func TestGetOverrideArgsFor(t *testing.T) {
tests := []struct {
name string
certManagerObj v1alpha1.CertManager
deploymentName string
expectedArgs []string
expectError bool
errContains string
}{
{
name: "get override args for controller",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{
ControllerConfig: &v1alpha1.DeploymentConfig{
OverrideArgs: []string{"--v=4", "--feature-gates=ExperimentalGatewayAPISupport=true"},
},
},
},
deploymentName: certmanagerControllerDeployment,
expectedArgs: []string{"--v=4", "--feature-gates=ExperimentalGatewayAPISupport=true"},
},
{
name: "get override args for webhook",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{
WebhookConfig: &v1alpha1.DeploymentConfig{
OverrideArgs: []string{"--secure-port=10251"},
},
},
},
deploymentName: certmanagerWebhookDeployment,
expectedArgs: []string{"--secure-port=10251"},
},
{
name: "get override args for cainjector",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{
CAInjectorConfig: &v1alpha1.DeploymentConfig{
OverrideArgs: []string{"--leader-elect=false"},
},
},
},
deploymentName: certmanagerCAinjectorDeployment,
expectedArgs: []string{"--leader-elect=false"},
},
{
name: "nil config returns nil args for controller",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{},
},
deploymentName: certmanagerControllerDeployment,
expectedArgs: nil,
},
{
name: "unsupported deployment name returns error",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{},
},
deploymentName: "unknown-deployment",
expectError: true,
errContains: "unsupported deployment name",
},
}

ctx := t.Context()
fakeClient, certManagerInformers, certManagerChan := setupSyncedFakeCertManagerInformer(t, ctx)

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
withFakeCertManagerForTest(t, ctx, fakeClient, certManagerChan, &tc.certManagerObj)

actualArgs, err := getOverrideArgsFor(certManagerInformers, tc.deploymentName)
if tc.expectError {
require.Error(t, err)
assert.Contains(t, err.Error(), tc.errContains)
} else {
require.NoError(t, err)
require.Equal(t, tc.expectedArgs, actualArgs)
}
})
}
}

func TestGetOverrideEnvFor(t *testing.T) {
tests := []struct {
name string
certManagerObj v1alpha1.CertManager
deploymentName string
expectedEnv []corev1.EnvVar
expectError bool
errContains string
}{
{
name: "get override env for controller",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{
ControllerConfig: &v1alpha1.DeploymentConfig{
OverrideEnv: []corev1.EnvVar{
{Name: "HTTP_PROXY", Value: "http://proxy:3128"},
},
},
},
},
deploymentName: certmanagerControllerDeployment,
expectedEnv: []corev1.EnvVar{
{Name: "HTTP_PROXY", Value: "http://proxy:3128"},
},
},
{
name: "get override env for webhook",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{
WebhookConfig: &v1alpha1.DeploymentConfig{
OverrideEnv: []corev1.EnvVar{
{Name: "MY_VAR", Value: "my-value"},
},
},
},
},
deploymentName: certmanagerWebhookDeployment,
expectedEnv: []corev1.EnvVar{
{Name: "MY_VAR", Value: "my-value"},
},
},
{
name: "get override env for cainjector",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{
CAInjectorConfig: &v1alpha1.DeploymentConfig{
OverrideEnv: []corev1.EnvVar{
{Name: "NO_PROXY", Value: "localhost"},
},
},
},
},
deploymentName: certmanagerCAinjectorDeployment,
expectedEnv: []corev1.EnvVar{
{Name: "NO_PROXY", Value: "localhost"},
},
},
{
name: "nil config returns nil env",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{},
},
deploymentName: certmanagerControllerDeployment,
expectedEnv: nil,
},
{
name: "unsupported deployment name returns error",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{},
},
deploymentName: "unknown-deployment",
expectError: true,
errContains: "unsupported deployment name",
},
}

ctx := t.Context()
fakeClient, certManagerInformers, certManagerChan := setupSyncedFakeCertManagerInformer(t, ctx)

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
withFakeCertManagerForTest(t, ctx, fakeClient, certManagerChan, &tc.certManagerObj)

actualEnv, err := getOverrideEnvFor(certManagerInformers, tc.deploymentName)
if tc.expectError {
require.Error(t, err)
assert.Contains(t, err.Error(), tc.errContains)
} else {
require.NoError(t, err)
require.Equal(t, tc.expectedEnv, actualEnv)
}
})
}
}

func TestGetOverridePodLabelsFor(t *testing.T) {
tests := []struct {
name string
certManagerObj v1alpha1.CertManager
deploymentName string
expectedLabels map[string]string
expectError bool
errContains string
}{
{
name: "get override labels for controller",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{
ControllerConfig: &v1alpha1.DeploymentConfig{
OverrideLabels: map[string]string{
"custom-label": "custom-value",
},
},
},
},
deploymentName: certmanagerControllerDeployment,
expectedLabels: map[string]string{
"custom-label": "custom-value",
},
},
{
name: "get override labels for webhook",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{
WebhookConfig: &v1alpha1.DeploymentConfig{
OverrideLabels: map[string]string{
"env": "production",
},
},
},
},
deploymentName: certmanagerWebhookDeployment,
expectedLabels: map[string]string{
"env": "production",
},
},
{
name: "get override labels for cainjector",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{
CAInjectorConfig: &v1alpha1.DeploymentConfig{
OverrideLabels: map[string]string{
"team": "security",
},
},
},
},
deploymentName: certmanagerCAinjectorDeployment,
expectedLabels: map[string]string{
"team": "security",
},
},
{
name: "nil config returns nil labels",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{},
},
deploymentName: certmanagerControllerDeployment,
expectedLabels: nil,
},
{
name: "unsupported deployment name returns error",
certManagerObj: v1alpha1.CertManager{
ObjectMeta: metav1.ObjectMeta{Name: "cluster"},
Spec: v1alpha1.CertManagerSpec{},
},
deploymentName: "unknown-deployment",
expectError: true,
errContains: "unsupported deployment name",
},
}

ctx := t.Context()
fakeClient, certManagerInformers, certManagerChan := setupSyncedFakeCertManagerInformer(t, ctx)

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
withFakeCertManagerForTest(t, ctx, fakeClient, certManagerChan, &tc.certManagerObj)

actualLabels, err := getOverridePodLabelsFor(certManagerInformers, tc.deploymentName)
if tc.expectError {
require.Error(t, err)
assert.Contains(t, err.Error(), tc.errContains)
} else {
require.NoError(t, err)
require.Equal(t, tc.expectedLabels, actualLabels)
}
})
}
}

func TestGetOverrideReplicasFor(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -999,7 +1287,7 @@ func TestGetOverrideReplicasFor(t *testing.T) {
withFakeCertManagerForTest(t, ctx, fakeClient, certManagerChan, &tc.certManagerObj)

actualOverrideReplicas, err := getOverrideReplicasFor(certManagerInformers, tc.deploymentName)
assert.NoError(t, err)
require.NoError(t, err)
if tc.expectedOverrideReplicas == nil {
assert.Nil(t, actualOverrideReplicas)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ package certmanager
import (
"fmt"
"strconv"
"unsafe"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/apis/core"
corevalidation "k8s.io/kubernetes/pkg/apis/core/validation"
"k8s.io/utils/strings/slices"

Expand Down Expand Up @@ -363,10 +361,7 @@ func withPodSchedulingValidateHook(certmanagerinformer certmanagerinformer.CertM
func validateScheduling(scheduling v1alpha1.CertManagerScheduling, fldPath *field.Path) error {
errs := metav1validation.ValidateLabels(scheduling.NodeSelector, fldPath.Child("nodeSelector"))

// Convert corev1.Tolerations to core.Tolerations.
tolerations := *(*[]core.Toleration)(unsafe.Pointer(&scheduling.Tolerations))

errs = append(errs, corevalidation.ValidateTolerations(tolerations, fldPath.Child("tolerations"), corevalidation.PodValidationOptions{})...)
errs = append(errs, corevalidation.ValidateTolerations(common.ToCoreTolerations(scheduling.Tolerations), fldPath.Child("tolerations"), corevalidation.PodValidationOptions{})...)

return errs.ToAggregate()
}
Loading