argo-cd/notification_controller/controller/controller_test.go
May Zhang 0c6644bf8e
fix(notifications): Allow notifications controller to notify on all namespaces (#15702)
* Allow notifications controller to notify on all namespaces

This adds functionality to the notifications controller to be notified
of and send notifications for applications in any namespace. The
namespaces to watch are controlled by the same --application-namespaces
and ARGOCD_APPLICATION_NAMESPACES variables as in the application
controller.

Signed-off-by: Nikolas Skoufis <nskoufis@seek.com.au>

* Add SEEK to users.md

Signed-off-by: Nikolas Skoufis <nskoufis@seek.com.au>

* Remove unused fields

Signed-off-by: Nikolas Skoufis <nskoufis@seek.com.au>

* Revert changes to Procfile

Signed-off-by: Nik Skoufis <n.skoufis@gmail.com>

* Fix unit tests

Signed-off-by: Nikolas Skoufis <nskoufis@seek.com.au>

* - add argocd namespaces environment variable to notifications controller

Signed-off-by: Stewart Thomson <sthomson@wynshop.com>

* - add example cluster role rbac

Signed-off-by: Stewart Thomson <sthomson@wynshop.com>

* - only look for projects in the controller's namespace (argocd by default)

Signed-off-by: Stewart Thomson <sthomson@wynshop.com>

* - update base manifest

Signed-off-by: Stewart Thomson <sthomson@wynshop.com>

* - skip app processing in notification controller

Signed-off-by: Stewart Thomson <sthomson@wynshop.com>

* added unit test and updated doc

Signed-off-by: May Zhang <may_zhang@intuit.com>

* added unit test and updated doc

Signed-off-by: May Zhang <may_zhang@intuit.com>

* updated examples/k8s-rbac/argocd-server-applications/kustomization.yaml's resources

Signed-off-by: May Zhang <may_zhang@intuit.com>

---------

Signed-off-by: Nikolas Skoufis <nskoufis@seek.com.au>
Signed-off-by: Nik Skoufis <n.skoufis@gmail.com>
Signed-off-by: Stewart Thomson <sthomson@wynshop.com>
Signed-off-by: May Zhang <may_zhang@intuit.com>
Co-authored-by: Nikolas Skoufis <nskoufis@seek.com.au>
Co-authored-by: Nik Skoufis <n.skoufis@gmail.com>
Co-authored-by: Stewart Thomson <sthomson@wynshop.com>
2023-10-06 20:25:38 +00:00

192 lines
4.9 KiB
Go

package controller
import (
"context"
"testing"
"time"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/dynamic/fake"
k8sfake "k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/tools/cache"
)
func TestIsAppSyncStatusRefreshed(t *testing.T) {
logger, _ := test.NewNullLogger()
logEntry := logger.WithField("", "")
tests := []struct {
name string
app *unstructured.Unstructured
expectedValue bool
}{
{
name: "No OperationState",
app: &unstructured.Unstructured{
Object: map[string]interface{}{
"status": map[string]interface{}{},
},
},
expectedValue: true,
},
{
name: "No FinishedAt, Completed Phase",
app: &unstructured.Unstructured{
Object: map[string]interface{}{
"status": map[string]interface{}{
"operationState": map[string]interface{}{
"phase": "Succeeded",
},
},
},
},
expectedValue: false,
},
{
name: "FinishedAt After ReconciledAt & ObservedAt",
app: &unstructured.Unstructured{
Object: map[string]interface{}{
"status": map[string]interface{}{
"operationState": map[string]interface{}{
"finishedAt": "2021-01-01T01:05:00Z",
"phase": "Succeeded",
},
"reconciledAt": "2021-01-01T01:02:00Z",
"observedAt": "2021-01-01T01:04:00Z",
},
},
},
expectedValue: false,
},
{
name: "FinishedAt Before ReconciledAt & ObservedAt",
app: &unstructured.Unstructured{
Object: map[string]interface{}{
"status": map[string]interface{}{
"operationState": map[string]interface{}{
"finishedAt": "2021-01-01T01:02:00Z",
"phase": "Succeeded",
},
"reconciledAt": "2021-01-01T01:04:00Z",
"observedAt": "2021-01-01T01:06:00Z",
},
},
},
expectedValue: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actualValue := isAppSyncStatusRefreshed(test.app, logEntry)
assert.Equal(t, test.expectedValue, actualValue)
})
}
}
func TestGetAppProj_invalidProjectNestedString(t *testing.T) {
app := &unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{},
},
}
informer := cache.NewSharedIndexInformer(nil, nil, 0, nil)
proj := getAppProj(app, informer)
assert.Nil(t, proj)
}
func TestInit(t *testing.T) {
scheme := runtime.NewScheme()
err := v1alpha1.SchemeBuilder.AddToScheme(scheme)
if err != nil {
t.Fatalf("Error registering the resource: %v", err)
}
dynamicClient := fake.NewSimpleDynamicClient(scheme)
k8sClient := k8sfake.NewSimpleClientset()
appLabelSelector := "app=test"
nc := NewController(
k8sClient,
dynamicClient,
nil,
"default",
[]string{},
appLabelSelector,
nil,
"my-secret",
"my-configmap",
)
assert.NotNil(t, nc)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
err = nc.Init(ctx)
assert.NoError(t, err)
}
func TestInitTimeout(t *testing.T) {
scheme := runtime.NewScheme()
err := v1alpha1.SchemeBuilder.AddToScheme(scheme)
if err != nil {
t.Fatalf("Error registering the resource: %v", err)
}
dynamicClient := fake.NewSimpleDynamicClient(scheme)
k8sClient := k8sfake.NewSimpleClientset()
appLabelSelector := "app=test"
nc := NewController(
k8sClient,
dynamicClient,
nil,
"default",
[]string{},
appLabelSelector,
nil,
"my-secret",
"my-configmap",
)
assert.NotNil(t, nc)
// Use a short timeout to simulate a timeout during cache synchronization
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)
defer cancel()
err = nc.Init(ctx)
// Expect an error & add assertion for the error message
assert.Error(t, err)
assert.Equal(t, "Timed out waiting for caches to sync", err.Error())
}
func TestCheckAppNotInAdditionalNamespaces(t *testing.T) {
app := &unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{},
},
}
namespace := "argocd"
var applicationNamespaces []string
applicationNamespaces = append(applicationNamespaces, "namespace1")
applicationNamespaces = append(applicationNamespaces, "namespace2")
// app is in same namespace as controller's namespace
app.SetNamespace(namespace)
assert.False(t, checkAppNotInAdditionalNamespaces(app, namespace, applicationNamespaces))
// app is not in the namespace as controller's namespace, but it is in one of the applicationNamespaces
app.SetNamespace("namespace2")
assert.False(t, checkAppNotInAdditionalNamespaces(app, "", applicationNamespaces))
// app is not in the namespace as controller's namespace, and it is not in any of the applicationNamespaces
app.SetNamespace("namespace3")
assert.True(t, checkAppNotInAdditionalNamespaces(app, "", applicationNamespaces))
}