Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experimental reconcile/rest API metric sanity test to E2E Tests #84

Merged
merged 5 commits into from
Nov 19, 2024
Merged
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
1 change: 1 addition & 0 deletions .github/workflows/e2e_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ jobs:

test-e2e:
name: Run end-to-end tests
timeout-minutes: 90
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/rollouts_e2e_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
test-e2e:
name: Run end-to-end tests from upstream Argo Rollouts repo
runs-on: ubuntu-latest
timeout-minutes: 90
strategy:
matrix:
k3s-version: [ v1.28.2 ]
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ start-e2e-namespace-scoped-bg: ## Start the operator, to run the e2e tests

.PHONY: start-e2e-cluster-scoped-bg
start-e2e-cluster-scoped-bg: ## Start the operator, to run the e2e tests
RUN_IN_BACKGROUND=true hack/start-rollouts-manager-for-e2e-tests.sh
RUN_IN_BACKGROUND=true NAMESPACE_SCOPED_ARGO_ROLLOUTS=false hack/start-rollouts-manager-for-e2e-tests.sh


.PHONY: test-e2e-namespace-scoped
Expand All @@ -145,7 +145,7 @@ test-e2e-namespace-scoped: ## Run operator e2e tests

.PHONY: test-e2e-cluster-scoped
test-e2e-cluster-scoped: ## Run operator e2e tests
hack/run-rollouts-manager-e2e-tests.sh
NAMESPACE_SCOPED_ARGO_ROLLOUTS=false hack/run-rollouts-manager-e2e-tests.sh

.PHONY: start-test-e2e-all
start-test-e2e-all: start-e2e-namespace-scoped-bg test-e2e-namespace-scoped start-e2e-cluster-scoped-bg test-e2e-cluster-scoped
Expand Down
6 changes: 3 additions & 3 deletions controllers/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,12 @@ func (r *RolloutManagerReconciler) reconcileConfigMap(ctx context.Context, cr ro
actualConfigMap.Data[TrafficRouterPluginConfigMapKey] = string(desiredTrafficRouterPluginString)
actualConfigMap.Data[MetricPluginConfigMapKey] = string(desiredMetricPluginString)

log.Info("Updating Rollouts ConfigMap due to detected difference")

// Update the ConfigMap in the cluster
if err := r.Client.Update(ctx, actualConfigMap); err != nil {
return fmt.Errorf("failed to update ConfigMap: %v", err)
}
log.Info("ConfigMap updated successfully")

// Restarting rollouts pod only if configMap is updated
if err := r.restartRolloutsPod(ctx, cr.Namespace); err != nil {
return err
Expand Down Expand Up @@ -183,8 +183,8 @@ func (r *RolloutManagerReconciler) restartRolloutsPod(ctx context.Context, names

for i := range podList.Items {
pod := podList.Items[i]
log.Info("Deleting Rollouts Pod", "podName", pod.Name)
if pod.ObjectMeta.DeletionTimestamp == nil {
log.Info("Deleting Rollouts Pod", "podName", pod.Name)
if err := r.Client.Delete(ctx, &pod); err != nil {
if errors.IsNotFound(err) {
log.Info(fmt.Sprintf("Pod %s already deleted", pod.Name))
Expand Down
3 changes: 1 addition & 2 deletions controllers/configmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand All @@ -19,7 +18,7 @@ var _ = Describe("ConfigMap Test", func() {
var a v1alpha1.RolloutManager
var r *RolloutManagerReconciler
var sa *corev1.ServiceAccount
var existingDeployment *v1.Deployment
var existingDeployment *appsv1.Deployment
const trafficrouterPluginLocation = "https://custom-traffic-plugin-location"
const metricPluginLocation = "https://custom-metric-plugin-location"

Expand Down
22 changes: 12 additions & 10 deletions controllers/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (r *RolloutManagerReconciler) reconcileRolloutsServiceAccount(ctx context.C
normalizedLiveServiceAccount := liveServiceAccount.DeepCopy()
removeUserLabelsAndAnnotations(&normalizedLiveServiceAccount.ObjectMeta, cr)

if !reflect.DeepEqual(normalizedLiveServiceAccount.Labels, expectedServiceAccount.Labels) || !reflect.DeepEqual(normalizedLiveServiceAccount.Annotations, expectedServiceAccount.Annotations) {
if !areStringMapsEqual(normalizedLiveServiceAccount.Labels, expectedServiceAccount.Labels) || !areStringMapsEqual(normalizedLiveServiceAccount.Annotations, expectedServiceAccount.Annotations) {
updateNeeded = true
log.Info(fmt.Sprintf("Labels/Annotations of ServiceAccount %s do not match the expected state, hence updating it", liveServiceAccount.Name))

Expand Down Expand Up @@ -111,7 +111,7 @@ func (r *RolloutManagerReconciler) reconcileRolloutsRole(ctx context.Context, cr

removeUserLabelsAndAnnotations(&normalizedLiveRole.ObjectMeta, cr)

if !reflect.DeepEqual(normalizedLiveRole.Labels, expectedRole.Labels) || !reflect.DeepEqual(normalizedLiveRole.Annotations, expectedRole.Annotations) {
if !areStringMapsEqual(normalizedLiveRole.Labels, expectedRole.Labels) || !areStringMapsEqual(normalizedLiveRole.Annotations, expectedRole.Annotations) {
updateNeeded = true
log.Info(fmt.Sprintf("Labels/Annotations of Role %s do not match the expected state, hence updating it", liveRole.Name))

Expand Down Expand Up @@ -165,7 +165,7 @@ func (r *RolloutManagerReconciler) reconcileRolloutsClusterRole(ctx context.Cont
normalizedLiveClusterRole := liveClusterRole.DeepCopy()
removeUserLabelsAndAnnotations(&normalizedLiveClusterRole.ObjectMeta, cr)

if !reflect.DeepEqual(normalizedLiveClusterRole.Labels, expectedClusterRole.Labels) || !reflect.DeepEqual(normalizedLiveClusterRole.Annotations, expectedClusterRole.Annotations) {
if !areStringMapsEqual(normalizedLiveClusterRole.Labels, expectedClusterRole.Labels) || !areStringMapsEqual(normalizedLiveClusterRole.Annotations, expectedClusterRole.Annotations) {
updateNeeded = true
log.Info(fmt.Sprintf("Labels/Annotations of Role %s do not match the expected state, hence updating it", liveClusterRole.Name))

Expand Down Expand Up @@ -248,7 +248,7 @@ func (r *RolloutManagerReconciler) reconcileRolloutsRoleBinding(ctx context.Cont

normalizedLiveRoleBinding := liveRoleBinding.DeepCopy()
removeUserLabelsAndAnnotations(&normalizedLiveRoleBinding.ObjectMeta, cr)
if !reflect.DeepEqual(normalizedLiveRoleBinding.Labels, expectedRoleBinding.Labels) || !reflect.DeepEqual(normalizedLiveRoleBinding.Annotations, expectedRoleBinding.Annotations) {
if !areStringMapsEqual(normalizedLiveRoleBinding.Labels, expectedRoleBinding.Labels) || !areStringMapsEqual(normalizedLiveRoleBinding.Annotations, expectedRoleBinding.Annotations) {
updateNeeded = true
log.Info(fmt.Sprintf("Labels/Annotations of RoleBinding %s do not match the expected state, hence updating it", liveRoleBinding.Name))

Expand Down Expand Up @@ -327,7 +327,7 @@ func (r *RolloutManagerReconciler) reconcileRolloutsClusterRoleBinding(ctx conte

normalizedLiveClusterRoleBinding := liveClusterRoleBinding.DeepCopy()
removeUserLabelsAndAnnotations(&normalizedLiveClusterRoleBinding.ObjectMeta, cr)
if !reflect.DeepEqual(normalizedLiveClusterRoleBinding.Labels, expectedClusterRoleBinding.Labels) || !reflect.DeepEqual(normalizedLiveClusterRoleBinding.Annotations, expectedClusterRoleBinding.Annotations) {
if !areStringMapsEqual(normalizedLiveClusterRoleBinding.Labels, expectedClusterRoleBinding.Labels) || !areStringMapsEqual(normalizedLiveClusterRoleBinding.Annotations, expectedClusterRoleBinding.Annotations) {
updateNeeded = true
log.Info(fmt.Sprintf("Labels/Annotations of ClusterRoleBinding %s do not match the expected state, hence updating it", liveClusterRoleBinding.Name))

Expand Down Expand Up @@ -460,7 +460,7 @@ func (r *RolloutManagerReconciler) reconcileRolloutsAggregateToAdminClusterRole(

normalizedLiveClusterRole := liveClusterRole.DeepCopy()
removeUserLabelsAndAnnotations(&normalizedLiveClusterRole.ObjectMeta, cr)
if !reflect.DeepEqual(normalizedLiveClusterRole.Labels, expectedClusterRole.Labels) || !reflect.DeepEqual(normalizedLiveClusterRole.Annotations, expectedClusterRole.Annotations) {
if !areStringMapsEqual(normalizedLiveClusterRole.Labels, expectedClusterRole.Labels) || !areStringMapsEqual(normalizedLiveClusterRole.Annotations, expectedClusterRole.Annotations) {
updateNeeded = true
log.Info(fmt.Sprintf("Labels/Annotations of aggregated ClusterRole %s do not match the expected state, hence updating it", liveClusterRole.Name))

Expand Down Expand Up @@ -512,7 +512,7 @@ func (r *RolloutManagerReconciler) reconcileRolloutsAggregateToEditClusterRole(c

normalizedLiveClusterRole := liveClusterRole.DeepCopy()
removeUserLabelsAndAnnotations(&normalizedLiveClusterRole.ObjectMeta, cr)
if !reflect.DeepEqual(normalizedLiveClusterRole.Labels, expectedClusterRole.Labels) || !reflect.DeepEqual(normalizedLiveClusterRole.Annotations, expectedClusterRole.Annotations) {
if !areStringMapsEqual(normalizedLiveClusterRole.Labels, expectedClusterRole.Labels) || !areStringMapsEqual(normalizedLiveClusterRole.Annotations, expectedClusterRole.Annotations) {
updateNeeded = true
log.Info(fmt.Sprintf("Labels/Annotations of aggregated ClusterRole %s do not match the expected state, hence updating it", liveClusterRole.Name))

Expand Down Expand Up @@ -564,7 +564,8 @@ func (r *RolloutManagerReconciler) reconcileRolloutsAggregateToViewClusterRole(c

normalizedLiveClusterRole := liveClusterRole.DeepCopy()
removeUserLabelsAndAnnotations(&normalizedLiveClusterRole.ObjectMeta, cr)
if !reflect.DeepEqual(normalizedLiveClusterRole.Labels, expectedClusterRole.Labels) || !reflect.DeepEqual(normalizedLiveClusterRole.Annotations, expectedClusterRole.Annotations) {
if !areStringMapsEqual(normalizedLiveClusterRole.Labels, expectedClusterRole.Labels) || !areStringMapsEqual(normalizedLiveClusterRole.Annotations, expectedClusterRole.Annotations) {

updateNeeded = true
log.Info(fmt.Sprintf("Labels/Annotations of aggregated ClusterRole %s do not match the expected state, hence updating it", liveClusterRole.Name))

Expand Down Expand Up @@ -702,7 +703,8 @@ func (r *RolloutManagerReconciler) reconcileRolloutsMetricsService(ctx context.C

normalizedLiveService := liveService.DeepCopy()
removeUserLabelsAndAnnotations(&normalizedLiveService.ObjectMeta, cr)
if !reflect.DeepEqual(normalizedLiveService.Labels, expectedSvc.Labels) || !reflect.DeepEqual(normalizedLiveService.Annotations, expectedSvc.Annotations) {
if !areStringMapsEqual(normalizedLiveService.Labels, expectedSvc.Labels) || !areStringMapsEqual(normalizedLiveService.Annotations, expectedSvc.Annotations) {

updateNeeded = true
log.Info(fmt.Sprintf("Labels/Annotations of metrics Service %s do not match the expected state, hence updating it", liveService.Name))

Expand Down Expand Up @@ -778,7 +780,7 @@ func (r *RolloutManagerReconciler) reconcileRolloutsSecrets(ctx context.Context,
normalizedLiveSecret := liveSecret.DeepCopy()
removeUserLabelsAndAnnotations(&normalizedLiveSecret.ObjectMeta, cr)

if !reflect.DeepEqual(normalizedLiveSecret.Labels, expectedSecret.Labels) || !reflect.DeepEqual(normalizedLiveSecret.Annotations, expectedSecret.Annotations) {
if !areStringMapsEqual(normalizedLiveSecret.Labels, expectedSecret.Labels) || !areStringMapsEqual(normalizedLiveSecret.Annotations, expectedSecret.Annotations) {
updateNeeded = true
log.Info(fmt.Sprintf("Labels/Annotations of Secret %s do not match the expected state, hence updating it", liveSecret.Name))

Expand Down
30 changes: 30 additions & 0 deletions controllers/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"os"
"reflect"
"sort"
"strings"

Expand Down Expand Up @@ -86,6 +87,30 @@ func appendStringMap(src map[string]string, add map[string]string) map[string]st
return res
}

// In go, reflect.DeepEqual(a, b), on maps a and b, will return false even when len(a) == 0 and len(b) == 0. This is due to a nil map being considered different from an empty map.
// This function handles this case better: if maps both have a length of 0, we consider them always equal.
func areStringMapsEqual(one map[string]string, two map[string]string) bool {

isOneEmpty := false

isTwoEmpty := false

if len(one) == 0 {
isOneEmpty = true
}

if len(two) == 0 {
isTwoEmpty = true
}

if isOneEmpty && isTwoEmpty {
return true
}

return reflect.DeepEqual(one, two)

}

// combineStringMaps will combine multiple maps: maps defined earlier in the 'maps' slice may have their values overriden by maps defined later in the 'maps' slice.
func combineStringMaps(maps ...map[string]string) map[string]string {

Expand Down Expand Up @@ -448,6 +473,11 @@ func removeUserLabelsAndAnnotations(obj *metav1.ObjectMeta, cr rolloutsmanagerv1

for objectLabelKey := range obj.Labels {

// We add this label to the aggregated cluster roles we generate, so we should not process it as a user label.
if strings.Contains(objectLabelKey, "rbac.authorization.k8s.io/") && strings.Contains(objectLabelKey, "aggregate") {
continue
}

existsInDefault := false

for defaultLabelKey := range defaultLabelsAndAnnotations.Labels {
Expand Down
61 changes: 43 additions & 18 deletions controllers/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,42 +452,36 @@ var _ = Describe("removeUserLabelsAndAnnotations tests", func() {
}

Expect(k8sClient.Create(ctx, &cr)).To(Succeed())
setRolloutsLabelsAndAnnotations(&obj)

removeUserLabelsAndAnnotations(&obj, cr)

Expect(obj.Labels).To(Equal(expectedLabels))
Expect(obj.Annotations).To(Equal(expectedAnnotations))
},
Entry("when no user-defined labels or annotations exist",
map[string]string{}, map[string]string{},
map[string]string{"app.kubernetes.io/name": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/part-of": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/component": DefaultArgoRolloutsResourceName},
map[string]string{},
map[string]string{},
map[string]string{},
map[string]string{},
),
Entry("when user-defined labels and annotations are present",
map[string]string{"user-label": "value"}, map[string]string{"user-annotation": "value"},
map[string]string{"app.kubernetes.io/name": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/part-of": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/component": DefaultArgoRolloutsResourceName},
map[string]string{"user-label": "value"},
map[string]string{"user-annotation": "value"},
map[string]string{},
map[string]string{},
),
Entry("when user-defined labels are present and annotations are empty",
map[string]string{"user-label": "value"}, map[string]string{},
map[string]string{"app.kubernetes.io/name": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/part-of": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/component": DefaultArgoRolloutsResourceName},
map[string]string{"user-label": "value"},
map[string]string{},
map[string]string{},
map[string]string{},
),
Entry("when user-defined labels are empty and annotations are present",
map[string]string{}, map[string]string{"user-annotation": "value"},
map[string]string{"app.kubernetes.io/name": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/part-of": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/component": DefaultArgoRolloutsResourceName},
map[string]string{},
map[string]string{"user-annotation": "value"},
map[string]string{},
map[string]string{},
),

Entry("when both user and non-user-defined labels are present, and annotations are empty",
map[string]string{"user-label": "value",
"app.kubernetes.io/name": DefaultArgoRolloutsResourceName,
Expand All @@ -499,6 +493,20 @@ var _ = Describe("removeUserLabelsAndAnnotations tests", func() {
"app.kubernetes.io/component": DefaultArgoRolloutsResourceName},
map[string]string{},
),
Entry("rbac aggregate-to- labels should not be removed, as we add these to ClusterRoles",
map[string]string{
"rbac.authorization.k8s.io/aggregate-to-admin": "true",
"app.kubernetes.io/name": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/part-of": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/component": DefaultArgoRolloutsResourceName},
map[string]string{},
map[string]string{
"rbac.authorization.k8s.io/aggregate-to-admin": "true",
"app.kubernetes.io/name": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/part-of": DefaultArgoRolloutsResourceName,
"app.kubernetes.io/component": DefaultArgoRolloutsResourceName},
map[string]string{},
),
)
})

Expand Down Expand Up @@ -683,6 +691,23 @@ var _ = Describe("setAdditionalRolloutsLabelsAndAnnotationsToObject tests", func
})
})

var _ = Describe("areStringMapsEqual tests", func() {
DescribeTable("areStringMapsEqual should match reflect.DeepEqual(), except when comparing nil with empty map", func(one map[string]string, two map[string]string, expectedRes bool) {

res := areStringMapsEqual(one, two)
Expect(res).To(Equal(expectedRes))
},
Entry("both nil", nil, nil, true),
Entry("one nil, one empty", map[string]string{}, nil, true),
Entry("one empty, one nil", nil, map[string]string{}, true),
Entry("both empty", map[string]string{}, map[string]string{}, true),
Entry("one empty, one has value", map[string]string{}, map[string]string{"key": "value"}, false),
Entry("one has value, one nil", map[string]string{"key": "value"}, nil, false),
Entry("equal values", map[string]string{"key": "value"}, map[string]string{"key": "value"}, true),
)

})

var _ = Describe("envMerge tests", func() {
DescribeTable("merges two slices of EnvVar entries",
func(existing, merge, expected []corev1.EnvVar, override bool) {
Expand Down
Loading
Loading