github.com/argoproj/argo-cd/v3@v3.2.1/cmd/argocd/commands/admin/app_test.go (about)

     1  package admin
     2  
     3  import (
     4  	"testing"
     5  
     6  	clustermocks "github.com/argoproj/gitops-engine/pkg/cache/mocks"
     7  	"github.com/argoproj/gitops-engine/pkg/health"
     8  	"github.com/argoproj/gitops-engine/pkg/utils/kube"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/mock"
    11  	"github.com/stretchr/testify/require"
    12  	corev1 "k8s.io/api/core/v1"
    13  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    14  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    15  	kubefake "k8s.io/client-go/kubernetes/fake"
    16  	"k8s.io/client-go/tools/cache"
    17  
    18  	"github.com/argoproj/argo-cd/v3/common"
    19  	statecache "github.com/argoproj/argo-cd/v3/controller/cache"
    20  	cachemocks "github.com/argoproj/argo-cd/v3/controller/cache/mocks"
    21  	"github.com/argoproj/argo-cd/v3/controller/metrics"
    22  	"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
    23  	appfake "github.com/argoproj/argo-cd/v3/pkg/client/clientset/versioned/fake"
    24  	argocdclient "github.com/argoproj/argo-cd/v3/reposerver/apiclient"
    25  	"github.com/argoproj/argo-cd/v3/reposerver/apiclient/mocks"
    26  	"github.com/argoproj/argo-cd/v3/test"
    27  	"github.com/argoproj/argo-cd/v3/util/argo/normalizers"
    28  	"github.com/argoproj/argo-cd/v3/util/db"
    29  	"github.com/argoproj/argo-cd/v3/util/settings"
    30  )
    31  
    32  func TestGetReconcileResults(t *testing.T) {
    33  	ctx := t.Context()
    34  
    35  	appClientset := appfake.NewSimpleClientset(&v1alpha1.Application{
    36  		ObjectMeta: metav1.ObjectMeta{
    37  			Name:      "test",
    38  			Namespace: "default",
    39  		},
    40  		Status: v1alpha1.ApplicationStatus{
    41  			Health: v1alpha1.AppHealthStatus{Status: health.HealthStatusHealthy},
    42  			Sync:   v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeOutOfSync},
    43  		},
    44  	})
    45  
    46  	result, err := getReconcileResults(ctx, appClientset, "default", "")
    47  	require.NoError(t, err)
    48  
    49  	expectedResults := []appReconcileResult{{
    50  		Name:   "test",
    51  		Health: health.HealthStatusHealthy,
    52  		Sync:   &v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeOutOfSync},
    53  	}}
    54  	assert.ElementsMatch(t, expectedResults, result)
    55  }
    56  
    57  func TestGetReconcileResults_Refresh(t *testing.T) {
    58  	ctx := t.Context()
    59  
    60  	argoCM := &corev1.ConfigMap{
    61  		ObjectMeta: metav1.ObjectMeta{
    62  			Name:      common.ArgoCDConfigMapName,
    63  			Namespace: "default",
    64  			Labels: map[string]string{
    65  				"app.kubernetes.io/part-of": "argocd",
    66  			},
    67  		},
    68  	}
    69  	argoCDSecret := &corev1.Secret{
    70  		ObjectMeta: metav1.ObjectMeta{
    71  			Name:      common.ArgoCDSecretName,
    72  			Namespace: "default",
    73  			Labels: map[string]string{
    74  				"app.kubernetes.io/part-of": "argocd",
    75  			},
    76  		},
    77  		Data: map[string][]byte{
    78  			"admin.password":   nil,
    79  			"server.secretkey": nil,
    80  		},
    81  	}
    82  	proj := &v1alpha1.AppProject{
    83  		ObjectMeta: metav1.ObjectMeta{
    84  			Name:      "default",
    85  			Namespace: "default",
    86  		},
    87  		Spec: v1alpha1.AppProjectSpec{Destinations: []v1alpha1.ApplicationDestination{{Namespace: "*", Server: "*"}}},
    88  	}
    89  
    90  	app := &v1alpha1.Application{
    91  		ObjectMeta: metav1.ObjectMeta{
    92  			Name:      "test",
    93  			Namespace: "default",
    94  		},
    95  		Spec: v1alpha1.ApplicationSpec{
    96  			Source:  &v1alpha1.ApplicationSource{},
    97  			Project: "default",
    98  			Destination: v1alpha1.ApplicationDestination{
    99  				Server:    v1alpha1.KubernetesInternalAPIServerAddr,
   100  				Namespace: "default",
   101  			},
   102  		},
   103  	}
   104  
   105  	appClientset := appfake.NewSimpleClientset(app, proj)
   106  	deployment := test.NewDeployment()
   107  	kubeClientset := kubefake.NewClientset(deployment, argoCM, argoCDSecret)
   108  	clusterCache := clustermocks.ClusterCache{}
   109  	clusterCache.On("IsNamespaced", mock.Anything).Return(true, nil)
   110  	clusterCache.On("GetGVKParser", mock.Anything).Return(nil)
   111  	repoServerClient := mocks.RepoServerServiceClient{}
   112  	repoServerClient.On("GenerateManifest", mock.Anything, mock.Anything).Return(&argocdclient.ManifestResponse{
   113  		Manifests: []string{test.DeploymentManifest},
   114  	}, nil)
   115  	repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
   116  	liveStateCache := cachemocks.LiveStateCache{}
   117  	liveStateCache.On("GetManagedLiveObjs", mock.Anything, mock.Anything, mock.Anything).Return(map[kube.ResourceKey]*unstructured.Unstructured{
   118  		kube.GetResourceKey(deployment): deployment,
   119  	}, nil)
   120  	liveStateCache.On("GetVersionsInfo", mock.Anything).Return("v1.2.3", nil, nil)
   121  	liveStateCache.On("Init").Return(nil, nil)
   122  	liveStateCache.On("GetClusterCache", mock.Anything).Return(&clusterCache, nil)
   123  	liveStateCache.On("IsNamespaced", mock.Anything, mock.Anything).Return(true, nil)
   124  
   125  	result, err := reconcileApplications(ctx, kubeClientset, appClientset, "default", &repoServerClientset, "",
   126  		func(_ db.ArgoDB, _ cache.SharedIndexInformer, _ *settings.SettingsManager, _ *metrics.MetricsServer) statecache.LiveStateCache {
   127  			return &liveStateCache
   128  		},
   129  		false,
   130  		normalizers.IgnoreNormalizerOpts{},
   131  	)
   132  
   133  	require.NoError(t, err)
   134  
   135  	assert.Equal(t, health.HealthStatusMissing, result[0].Health)
   136  	assert.Equal(t, v1alpha1.SyncStatusCodeOutOfSync, result[0].Sync.Status)
   137  }
   138  
   139  func TestDiffReconcileResults_NoDifferences(t *testing.T) {
   140  	logs, err := captureStdout(func() {
   141  		require.NoError(t, diffReconcileResults(
   142  			reconcileResults{Applications: []appReconcileResult{{
   143  				Name: "app1",
   144  				Sync: &v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeOutOfSync},
   145  			}}},
   146  			reconcileResults{Applications: []appReconcileResult{{
   147  				Name: "app1",
   148  				Sync: &v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeOutOfSync},
   149  			}}},
   150  		))
   151  	})
   152  	require.NoError(t, err)
   153  	assert.Equal(t, "app1\n", logs)
   154  }
   155  
   156  func TestDiffReconcileResults_DifferentApps(t *testing.T) {
   157  	logs, err := captureStdout(func() {
   158  		require.NoError(t, diffReconcileResults(
   159  			reconcileResults{Applications: []appReconcileResult{{
   160  				Name: "app1",
   161  				Sync: &v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeOutOfSync},
   162  			}, {
   163  				Name: "app2",
   164  				Sync: &v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeOutOfSync},
   165  			}}},
   166  			reconcileResults{Applications: []appReconcileResult{{
   167  				Name: "app1",
   168  				Sync: &v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeOutOfSync},
   169  			}, {
   170  				Name: "app3",
   171  				Sync: &v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeOutOfSync},
   172  			}}},
   173  		))
   174  	})
   175  	require.NoError(t, err)
   176  	assert.Equal(t, `app1
   177  app2
   178  1,9d0
   179  < conditions: null
   180  < health: ""
   181  < name: app2
   182  < sync:
   183  <   comparedTo:
   184  <     destination: {}
   185  <     source:
   186  <       repoURL: ""
   187  <   status: OutOfSync
   188  app3
   189  0a1,9
   190  > conditions: null
   191  > health: ""
   192  > name: app3
   193  > sync:
   194  >   comparedTo:
   195  >     destination: {}
   196  >     source:
   197  >       repoURL: ""
   198  >   status: OutOfSync
   199  `, logs)
   200  }