github.com/argoproj-labs/argocd-operator@v0.10.0/controllers/argocd/status_test.go (about)

     1  package argocd
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	argoproj "github.com/argoproj-labs/argocd-operator/api/v1beta1"
     8  
     9  	oappsv1 "github.com/openshift/api/apps/v1"
    10  	configv1 "github.com/openshift/api/config/v1"
    11  	routev1 "github.com/openshift/api/route/v1"
    12  	"github.com/stretchr/testify/assert"
    13  	networkingv1 "k8s.io/api/networking/v1"
    14  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  	"k8s.io/apimachinery/pkg/runtime"
    16  	"sigs.k8s.io/controller-runtime/pkg/client"
    17  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    18  )
    19  
    20  func TestReconcileArgoCD_reconcileStatusKeycloak_K8s(t *testing.T) {
    21  	logf.SetLogger(ZapLogger(true))
    22  
    23  	a := makeTestArgoCDForKeycloak()
    24  
    25  	resObjs := []client.Object{a}
    26  	subresObjs := []client.Object{a}
    27  	runtimeObjs := []runtime.Object{}
    28  	sch := makeTestReconcilerScheme(argoproj.AddToScheme)
    29  	cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
    30  	r := makeTestReconciler(cl, sch)
    31  
    32  	assert.NoError(t, createNamespace(r, a.Namespace, ""))
    33  
    34  	d := newKeycloakDeployment(a)
    35  
    36  	// keycloak not installed
    37  	_ = r.reconcileStatusKeycloak(a)
    38  	assert.Equal(t, "Unknown", a.Status.SSO)
    39  
    40  	// keycloak installation started
    41  	r.Client.Create(context.TODO(), d)
    42  
    43  	_ = r.reconcileStatusKeycloak(a)
    44  	assert.Equal(t, "Pending", a.Status.SSO)
    45  
    46  	// keycloak installation completed
    47  	d.Status.ReadyReplicas = *d.Spec.Replicas
    48  	r.Client.Status().Update(context.TODO(), d)
    49  
    50  	_ = r.reconcileStatusKeycloak(a)
    51  	assert.Equal(t, "Running", a.Status.SSO)
    52  }
    53  
    54  func TestReconcileArgoCD_reconcileStatusKeycloak_OpenShift(t *testing.T) {
    55  	logf.SetLogger(ZapLogger(true))
    56  
    57  	a := makeTestArgoCDForKeycloak()
    58  
    59  	resObjs := []client.Object{a}
    60  	subresObjs := []client.Object{a}
    61  	runtimeObjs := []runtime.Object{}
    62  	sch := makeTestReconcilerScheme(argoproj.AddToScheme)
    63  	cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
    64  	r := makeTestReconciler(cl, sch)
    65  
    66  	assert.NoError(t, createNamespace(r, a.Namespace, ""))
    67  
    68  	assert.NoError(t, oappsv1.Install(r.Scheme))
    69  	templateAPIFound = true
    70  	defer removeTemplateAPI()
    71  
    72  	dc := getKeycloakDeploymentConfigTemplate(a)
    73  	dc.ObjectMeta.Name = defaultKeycloakIdentifier
    74  
    75  	// keycloak not installed
    76  	_ = r.reconcileStatusKeycloak(a)
    77  	assert.Equal(t, "Unknown", a.Status.SSO)
    78  
    79  	// create new client with dc object already present, but with 0 ready replicas to simulate
    80  	// keycloak installation started
    81  	resObjs = append(resObjs, dc)
    82  	subresObjs = append(subresObjs, dc)
    83  	r.Client = makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
    84  
    85  	_ = r.reconcileStatusKeycloak(a)
    86  	assert.Equal(t, "Pending", a.Status.SSO)
    87  
    88  	// create new client with dc object already present, with 1 ready replica to simulate
    89  	// keycloak installation completed
    90  	dc.Status.ReadyReplicas = dc.Spec.Replicas
    91  	r.Client = makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
    92  
    93  	_ = r.reconcileStatusKeycloak(a)
    94  	assert.Equal(t, "Running", a.Status.SSO)
    95  }
    96  
    97  func TestReconcileArgoCD_reconcileStatusSSO(t *testing.T) {
    98  	logf.SetLogger(ZapLogger(true))
    99  
   100  	tests := []struct {
   101  		name          string
   102  		argoCD        *argoproj.ArgoCD
   103  		wantSSOStatus string
   104  	}{
   105  		{
   106  			name: "both dex and keycloak configured",
   107  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   108  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   109  					Provider: argoproj.SSOProviderTypeKeycloak,
   110  					Dex: &argoproj.ArgoCDDexSpec{
   111  						OpenShiftOAuth: true,
   112  					},
   113  				}
   114  			}),
   115  			wantSSOStatus: "Failed",
   116  		},
   117  		{
   118  			name: "sso provider dex but no .spec.sso.dex provided",
   119  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   120  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   121  					Provider: argoproj.SSOProviderTypeDex,
   122  				}
   123  			}),
   124  			wantSSOStatus: "Failed",
   125  		},
   126  		{
   127  			name: "no sso configured",
   128  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   129  				cr.Spec.SSO = nil
   130  			}),
   131  			wantSSOStatus: "Unknown",
   132  		},
   133  		{
   134  			name: "unsupported sso configured",
   135  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   136  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   137  					Provider: "Unsupported",
   138  					Dex: &argoproj.ArgoCDDexSpec{
   139  						OpenShiftOAuth: true,
   140  					},
   141  				}
   142  			}),
   143  			wantSSOStatus: "Failed",
   144  		},
   145  	}
   146  
   147  	for _, test := range tests {
   148  		t.Run(test.name, func(t *testing.T) {
   149  
   150  			resObjs := []client.Object{test.argoCD}
   151  			subresObjs := []client.Object{test.argoCD}
   152  			runtimeObjs := []runtime.Object{}
   153  			sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   154  			cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   155  			r := makeTestReconciler(cl, sch)
   156  
   157  			assert.NoError(t, createNamespace(r, test.argoCD.Namespace, ""))
   158  
   159  			r.reconcileSSO(test.argoCD)
   160  
   161  			r.reconcileStatusSSO(test.argoCD)
   162  
   163  			assert.Equal(t, test.wantSSOStatus, test.argoCD.Status.SSO)
   164  		})
   165  	}
   166  }
   167  
   168  func TestReconcileArgoCD_reconcileStatusHost(t *testing.T) {
   169  	logf.SetLogger(ZapLogger(true))
   170  
   171  	tests := []struct {
   172  		name              string
   173  		routeEnabled      bool
   174  		testRouteAPIFound bool
   175  		ingressEnabled    bool
   176  		expectedNil       bool
   177  		expectedHost      bool
   178  		host              string
   179  	}{
   180  		{
   181  			name:              "",
   182  			routeEnabled:      true,
   183  			testRouteAPIFound: true,
   184  			ingressEnabled:    false,
   185  			expectedNil:       false,
   186  			host:              "argocd",
   187  		},
   188  		{
   189  			name:              "",
   190  			routeEnabled:      false,
   191  			testRouteAPIFound: false,
   192  			ingressEnabled:    true,
   193  			expectedNil:       false,
   194  			host:              "argocd, 12.0.0.5",
   195  		},
   196  	}
   197  	for _, test := range tests {
   198  		t.Run(test.name, func(t *testing.T) {
   199  
   200  			routeAPIFound = test.testRouteAPIFound
   201  
   202  			a := makeTestArgoCD(func(a *argoproj.ArgoCD) {
   203  				a.Spec.Server.Route.Enabled = test.routeEnabled
   204  				a.Spec.Server.Ingress.Enabled = test.ingressEnabled
   205  			})
   206  
   207  			route := &routev1.Route{
   208  				ObjectMeta: metav1.ObjectMeta{
   209  					Name:      testArgoCDName + "-server",
   210  					Namespace: testNamespace,
   211  					Labels: map[string]string{
   212  						"app.kubernetes.io/name": testArgoCDName + "-server",
   213  					},
   214  				},
   215  				Spec: routev1.RouteSpec{
   216  					Host: "argocd",
   217  				},
   218  				Status: routev1.RouteStatus{
   219  					Ingress: []routev1.RouteIngress{
   220  						{
   221  							Host: "argocd",
   222  							Conditions: []routev1.RouteIngressCondition{
   223  								{
   224  									Type:   routev1.RouteAdmitted,
   225  									Status: "True",
   226  								},
   227  							},
   228  						},
   229  					},
   230  				},
   231  			}
   232  
   233  			ingress := &networkingv1.Ingress{
   234  				ObjectMeta: metav1.ObjectMeta{
   235  					Name:      testArgoCDName + "-server",
   236  					Namespace: testNamespace,
   237  				},
   238  				Status: networkingv1.IngressStatus{
   239  					LoadBalancer: networkingv1.IngressLoadBalancerStatus{
   240  						Ingress: []networkingv1.IngressLoadBalancerIngress{
   241  							{
   242  								IP:       "12.0.0.1",
   243  								Hostname: "argocd",
   244  								Ports:    []networkingv1.IngressPortStatus{},
   245  							},
   246  							{
   247  								IP:       "12.0.0.5",
   248  								Hostname: "",
   249  							},
   250  						},
   251  					},
   252  				},
   253  			}
   254  
   255  			resObjs := []client.Object{a}
   256  			subresObjs := []client.Object{a}
   257  			runtimeObjs := []runtime.Object{}
   258  			sch := makeTestReconcilerScheme(argoproj.AddToScheme, configv1.Install, routev1.Install)
   259  			cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   260  			r := makeTestReconciler(cl, sch)
   261  
   262  			if test.routeEnabled {
   263  				err := r.Client.Create(context.TODO(), route)
   264  				assert.NoError(t, err)
   265  
   266  			} else if test.ingressEnabled {
   267  				err := r.Client.Create(context.TODO(), ingress)
   268  				assert.NoError(t, err)
   269  				assert.NotEqual(t, "Pending", a.Status.Phase)
   270  			}
   271  
   272  			err := r.reconcileStatusHost(a)
   273  			assert.NoError(t, err)
   274  
   275  			assert.Equal(t, test.host, a.Status.Host)
   276  		})
   277  	}
   278  }
   279  
   280  func TestReconcileArgoCD_reconcileStatusNotificationsController(t *testing.T) {
   281  	logf.SetLogger(ZapLogger(true))
   282  	a := makeTestArgoCD()
   283  
   284  	resObjs := []client.Object{a}
   285  	subresObjs := []client.Object{a}
   286  	runtimeObjs := []runtime.Object{}
   287  	sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   288  	cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   289  	r := makeTestReconciler(cl, sch)
   290  
   291  	assert.NoError(t, r.reconcileStatusNotifications(a))
   292  	assert.Equal(t, "", a.Status.NotificationsController)
   293  
   294  	a.Spec.Notifications.Enabled = true
   295  	assert.NoError(t, r.reconcileNotificationsController(a))
   296  	assert.NoError(t, r.reconcileStatusNotifications(a))
   297  	assert.Equal(t, "Pending", a.Status.NotificationsController)
   298  
   299  	a.Spec.Notifications.Enabled = false
   300  	assert.NoError(t, r.deleteNotificationsResources(a))
   301  	assert.NoError(t, r.reconcileStatusNotifications(a))
   302  	assert.Equal(t, "", a.Status.NotificationsController)
   303  }
   304  
   305  func TestReconcileArgoCD_reconcileStatusApplicationSetController(t *testing.T) {
   306  	logf.SetLogger(ZapLogger(true))
   307  	a := makeTestArgoCD()
   308  
   309  	resObjs := []client.Object{a}
   310  	subresObjs := []client.Object{a}
   311  	runtimeObjs := []runtime.Object{}
   312  	sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   313  	cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   314  	r := makeTestReconciler(cl, sch)
   315  
   316  	assert.NoError(t, r.reconcileStatusApplicationSetController(a))
   317  	assert.Equal(t, "Unknown", a.Status.ApplicationSetController)
   318  
   319  	a.Spec.ApplicationSet = &argoproj.ArgoCDApplicationSet{}
   320  	assert.NoError(t, r.reconcileApplicationSetController(a))
   321  	assert.NoError(t, r.reconcileStatusApplicationSetController(a))
   322  	assert.Equal(t, "Pending", a.Status.ApplicationSetController)
   323  }