github.com/argoproj/argo-cd@v1.8.7/util/settings/settings_test.go (about)

     1  package settings
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/argoproj/argo-cd/common"
     8  	"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	v1 "k8s.io/api/core/v1"
    12  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    13  	"k8s.io/client-go/kubernetes/fake"
    14  )
    15  
    16  func fixtures(data map[string]string, opts ...func(secret *v1.Secret)) (*fake.Clientset, *SettingsManager) {
    17  	cm := &v1.ConfigMap{
    18  		ObjectMeta: metav1.ObjectMeta{
    19  			Name:      common.ArgoCDConfigMapName,
    20  			Namespace: "default",
    21  			Labels: map[string]string{
    22  				"app.kubernetes.io/part-of": "argocd",
    23  			},
    24  		},
    25  		Data: data,
    26  	}
    27  	secret := &v1.Secret{
    28  		ObjectMeta: metav1.ObjectMeta{
    29  			Name:      common.ArgoCDSecretName,
    30  			Namespace: "default",
    31  			Labels: map[string]string{
    32  				"app.kubernetes.io/part-of": "argocd",
    33  			},
    34  		},
    35  		Data: map[string][]byte{},
    36  	}
    37  	for i := range opts {
    38  		opts[i](secret)
    39  	}
    40  	kubeClient := fake.NewSimpleClientset(cm, secret)
    41  	settingsManager := NewSettingsManager(context.Background(), kubeClient, "default")
    42  
    43  	return kubeClient, settingsManager
    44  }
    45  
    46  func TestGetRepositories(t *testing.T) {
    47  	_, settingsManager := fixtures(map[string]string{
    48  		"repositories": "\n  - url: http://foo\n",
    49  	})
    50  	filter, err := settingsManager.GetRepositories()
    51  	assert.NoError(t, err)
    52  	assert.Equal(t, []Repository{{URL: "http://foo"}}, filter)
    53  }
    54  
    55  func TestSaveRepositories(t *testing.T) {
    56  	kubeClient, settingsManager := fixtures(nil)
    57  	err := settingsManager.SaveRepositories([]Repository{{URL: "http://foo"}})
    58  	assert.NoError(t, err)
    59  	cm, err := kubeClient.CoreV1().ConfigMaps("default").Get(context.Background(), common.ArgoCDConfigMapName, metav1.GetOptions{})
    60  	assert.NoError(t, err)
    61  	assert.Equal(t, cm.Data["repositories"], "- url: http://foo\n")
    62  
    63  	repos, err := settingsManager.GetRepositories()
    64  	assert.NoError(t, err)
    65  	assert.ElementsMatch(t, repos, []Repository{{URL: "http://foo"}})
    66  }
    67  
    68  func TestSaveRepositoriesNoConfigMap(t *testing.T) {
    69  	kubeClient := fake.NewSimpleClientset()
    70  	settingsManager := NewSettingsManager(context.Background(), kubeClient, "default")
    71  
    72  	err := settingsManager.SaveRepositories([]Repository{{URL: "http://foo"}})
    73  	assert.NoError(t, err)
    74  	cm, err := kubeClient.CoreV1().ConfigMaps("default").Get(context.Background(), common.ArgoCDConfigMapName, metav1.GetOptions{})
    75  	assert.NoError(t, err)
    76  	assert.Equal(t, cm.Data["repositories"], "- url: http://foo\n")
    77  }
    78  
    79  func TestSaveRepositoryCredentials(t *testing.T) {
    80  	kubeClient, settingsManager := fixtures(nil)
    81  	err := settingsManager.SaveRepositoryCredentials([]RepositoryCredentials{{URL: "http://foo"}})
    82  	assert.NoError(t, err)
    83  	cm, err := kubeClient.CoreV1().ConfigMaps("default").Get(context.Background(), common.ArgoCDConfigMapName, metav1.GetOptions{})
    84  	assert.NoError(t, err)
    85  	assert.Equal(t, cm.Data["repository.credentials"], "- url: http://foo\n")
    86  
    87  	creds, err := settingsManager.GetRepositoryCredentials()
    88  	assert.NoError(t, err)
    89  	assert.ElementsMatch(t, creds, []RepositoryCredentials{{URL: "http://foo"}})
    90  }
    91  
    92  func TestGetRepositoryCredentials(t *testing.T) {
    93  	_, settingsManager := fixtures(map[string]string{
    94  		"repository.credentials": "\n  - url: http://foo\n",
    95  	})
    96  	filter, err := settingsManager.GetRepositoryCredentials()
    97  	assert.NoError(t, err)
    98  	assert.Equal(t, []RepositoryCredentials{{URL: "http://foo"}}, filter)
    99  }
   100  
   101  func TestGetResourceFilter(t *testing.T) {
   102  	data := map[string]string{
   103  		"resource.exclusions": "\n  - apiGroups: [\"group1\"]\n    kinds: [\"kind1\"]\n    clusters: [\"cluster1\"]\n",
   104  		"resource.inclusions": "\n  - apiGroups: [\"group2\"]\n    kinds: [\"kind2\"]\n    clusters: [\"cluster2\"]\n",
   105  	}
   106  	_, settingsManager := fixtures(data)
   107  	filter, err := settingsManager.GetResourcesFilter()
   108  	assert.NoError(t, err)
   109  	assert.Equal(t, &ResourcesFilter{
   110  		ResourceExclusions: []FilteredResource{{APIGroups: []string{"group1"}, Kinds: []string{"kind1"}, Clusters: []string{"cluster1"}}},
   111  		ResourceInclusions: []FilteredResource{{APIGroups: []string{"group2"}, Kinds: []string{"kind2"}, Clusters: []string{"cluster2"}}},
   112  	}, filter)
   113  }
   114  
   115  func TestGetConfigManagementPlugins(t *testing.T) {
   116  	data := map[string]string{
   117  		"configManagementPlugins": `
   118        - name: kasane
   119          init:
   120            command: [kasane, update]
   121          generate:
   122            command: [kasane, show]`,
   123  	}
   124  	_, settingsManager := fixtures(data)
   125  	plugins, err := settingsManager.GetConfigManagementPlugins()
   126  	assert.NoError(t, err)
   127  	assert.ElementsMatch(t, []v1alpha1.ConfigManagementPlugin{{
   128  		Name:     "kasane",
   129  		Init:     &v1alpha1.Command{Command: []string{"kasane", "update"}},
   130  		Generate: v1alpha1.Command{Command: []string{"kasane", "show"}},
   131  	}}, plugins)
   132  }
   133  
   134  func TestGetAppInstanceLabelKey(t *testing.T) {
   135  	_, settingsManager := fixtures(map[string]string{
   136  		"application.instanceLabelKey": "testLabel",
   137  	})
   138  	label, err := settingsManager.GetAppInstanceLabelKey()
   139  	assert.NoError(t, err)
   140  	assert.Equal(t, "testLabel", label)
   141  }
   142  
   143  func TestGetResourceOverrides(t *testing.T) {
   144  	ignoreStatus := v1alpha1.ResourceOverride{IgnoreDifferences: v1alpha1.OverrideIgnoreDiff{
   145  		JSONPointers: []string{"/status"},
   146  	}}
   147  	crdGK := "apiextensions.k8s.io/CustomResourceDefinition"
   148  
   149  	_, settingsManager := fixtures(map[string]string{
   150  		"resource.customizations": `
   151      admissionregistration.k8s.io/MutatingWebhookConfiguration:
   152        ignoreDifferences: |
   153          jsonPointers:
   154          - /webhooks/0/clientConfig/caBundle`,
   155  	})
   156  	overrides, err := settingsManager.GetResourceOverrides()
   157  	assert.NoError(t, err)
   158  
   159  	webHookOverrides := overrides["admissionregistration.k8s.io/MutatingWebhookConfiguration"]
   160  	assert.NotNil(t, webHookOverrides)
   161  
   162  	assert.Equal(t, v1alpha1.ResourceOverride{
   163  		IgnoreDifferences: v1alpha1.OverrideIgnoreDiff{JSONPointers: []string{"/webhooks/0/clientConfig/caBundle"}},
   164  	}, webHookOverrides)
   165  
   166  	// by default, crd status should be ignored
   167  	crdOverrides := overrides[crdGK]
   168  	assert.NotNil(t, crdOverrides)
   169  	assert.Equal(t, ignoreStatus, crdOverrides)
   170  
   171  	// with value all, status of all objects should be ignored
   172  	_, settingsManager = fixtures(map[string]string{
   173  		"resource.compareoptions": `
   174      ignoreResourceStatusField: all`,
   175  	})
   176  	overrides, err = settingsManager.GetResourceOverrides()
   177  	assert.NoError(t, err)
   178  
   179  	globalOverrides := overrides["*/*"]
   180  	assert.NotNil(t, globalOverrides)
   181  	assert.Equal(t, ignoreStatus, globalOverrides)
   182  
   183  	// with value crd, status of crd objects should be ignored
   184  	_, settingsManager = fixtures(map[string]string{
   185  		"resource.compareoptions": `
   186      ignoreResourceStatusField: crd`,
   187  
   188  		"resource.customizations": `
   189      apiextensions.k8s.io/CustomResourceDefinition:
   190        ignoreDifferences: |
   191          jsonPointers:
   192          - /webhooks/0/clientConfig/caBundle`,
   193  	})
   194  	overrides, err = settingsManager.GetResourceOverrides()
   195  	assert.NoError(t, err)
   196  
   197  	crdOverrides = overrides[crdGK]
   198  	assert.NotNil(t, crdOverrides)
   199  	assert.Equal(t, v1alpha1.ResourceOverride{IgnoreDifferences: v1alpha1.OverrideIgnoreDiff{JSONPointers: []string{"/webhooks/0/clientConfig/caBundle", "/status"}}}, crdOverrides)
   200  
   201  	// with incorrect value, status of crd objects should be ignored
   202  	_, settingsManager = fixtures(map[string]string{
   203  		"resource.compareoptions": `
   204      ignoreResourceStatusField: foobar`,
   205  	})
   206  	overrides, err = settingsManager.GetResourceOverrides()
   207  	assert.NoError(t, err)
   208  
   209  	defaultOverrides := overrides[crdGK]
   210  	assert.NotNil(t, defaultOverrides)
   211  	assert.Equal(t, ignoreStatus, defaultOverrides)
   212  	assert.Equal(t, ignoreStatus, defaultOverrides)
   213  
   214  	// with value off, status of no objects should be ignored
   215  	_, settingsManager = fixtures(map[string]string{
   216  		"resource.compareoptions": `
   217      ignoreResourceStatusField: off`,
   218  	})
   219  	overrides, err = settingsManager.GetResourceOverrides()
   220  	assert.NoError(t, err)
   221  	assert.Equal(t, 0, len(overrides))
   222  
   223  }
   224  
   225  func TestSettingsManager_GetResourceOverrides_with_empty_string(t *testing.T) {
   226  	_, settingsManager := fixtures(map[string]string{
   227  		resourceCustomizationsKey: "",
   228  	})
   229  	overrides, err := settingsManager.GetResourceOverrides()
   230  	assert.NoError(t, err)
   231  
   232  	assert.Len(t, overrides, 1)
   233  }
   234  
   235  func TestGetResourceCompareOptions(t *testing.T) {
   236  	// ignoreAggregatedRules is true
   237  	{
   238  		_, settingsManager := fixtures(map[string]string{
   239  			"resource.compareoptions": "ignoreAggregatedRoles: true",
   240  		})
   241  		compareOptions, err := settingsManager.GetResourceCompareOptions()
   242  		assert.NoError(t, err)
   243  		assert.True(t, compareOptions.IgnoreAggregatedRoles)
   244  	}
   245  
   246  	// ignoreAggregatedRules is false
   247  	{
   248  		_, settingsManager := fixtures(map[string]string{
   249  			"resource.compareoptions": "ignoreAggregatedRoles: false",
   250  		})
   251  		compareOptions, err := settingsManager.GetResourceCompareOptions()
   252  		assert.NoError(t, err)
   253  		assert.False(t, compareOptions.IgnoreAggregatedRoles)
   254  	}
   255  
   256  	// The empty resource.compareoptions should result in default being returned
   257  	{
   258  		_, settingsManager := fixtures(map[string]string{
   259  			"resource.compareoptions": "",
   260  		})
   261  		compareOptions, err := settingsManager.GetResourceCompareOptions()
   262  		defaultOptions := GetDefaultDiffOptions()
   263  		assert.NoError(t, err)
   264  		assert.Equal(t, defaultOptions.IgnoreAggregatedRoles, compareOptions.IgnoreAggregatedRoles)
   265  	}
   266  
   267  	// resource.compareoptions not defined - should result in default being returned
   268  	{
   269  		_, settingsManager := fixtures(map[string]string{})
   270  		compareOptions, err := settingsManager.GetResourceCompareOptions()
   271  		defaultOptions := GetDefaultDiffOptions()
   272  		assert.NoError(t, err)
   273  		assert.Equal(t, defaultOptions.IgnoreAggregatedRoles, compareOptions.IgnoreAggregatedRoles)
   274  	}
   275  }
   276  
   277  func TestSettingsManager_GetKustomizeBuildOptions(t *testing.T) {
   278  	t.Run("Empty", func(t *testing.T) {
   279  		_, settingsManager := fixtures(map[string]string{})
   280  
   281  		settings, err := settingsManager.GetKustomizeSettings()
   282  
   283  		assert.NoError(t, err)
   284  		assert.Empty(t, settings.BuildOptions)
   285  		assert.Empty(t, settings.Versions)
   286  	})
   287  	t.Run("Set", func(t *testing.T) {
   288  		_, settingsManager := fixtures(map[string]string{
   289  			"kustomize.buildOptions":   "foo",
   290  			"kustomize.version.v3.2.1": "somePath",
   291  		})
   292  
   293  		options, err := settingsManager.GetKustomizeSettings()
   294  
   295  		assert.NoError(t, err)
   296  		assert.Equal(t, "foo", options.BuildOptions)
   297  		assert.Equal(t, []KustomizeVersion{{Name: "v3.2.1", Path: "somePath"}}, options.Versions)
   298  	})
   299  }
   300  
   301  func TestKustomizeSettings_GetOptions(t *testing.T) {
   302  	settings := KustomizeSettings{Versions: []KustomizeVersion{
   303  		{Name: "v1", Path: "path_v1"},
   304  		{Name: "v2", Path: "path_v2"},
   305  		{Name: "v3", Path: "path_v3"},
   306  	}}
   307  
   308  	t.Run("VersionDoesNotExist", func(t *testing.T) {
   309  		_, err := settings.GetOptions(v1alpha1.ApplicationSource{
   310  			Kustomize: &v1alpha1.ApplicationSourceKustomize{Version: "v4"}})
   311  		assert.Error(t, err)
   312  	})
   313  
   314  	t.Run("VersionExists", func(t *testing.T) {
   315  		ver, err := settings.GetOptions(v1alpha1.ApplicationSource{
   316  			Kustomize: &v1alpha1.ApplicationSourceKustomize{Version: "v2"}})
   317  		if !assert.NoError(t, err) {
   318  			return
   319  		}
   320  		assert.Equal(t, "path_v2", ver.BinaryPath)
   321  	})
   322  }
   323  
   324  func TestGetGoogleAnalytics(t *testing.T) {
   325  	_, settingsManager := fixtures(map[string]string{
   326  		"ga.trackingid": "123",
   327  	})
   328  	ga, err := settingsManager.GetGoogleAnalytics()
   329  	assert.NoError(t, err)
   330  	assert.Equal(t, "123", ga.TrackingID)
   331  	assert.Equal(t, true, ga.AnonymizeUsers)
   332  }
   333  
   334  func TestSettingsManager_GetHelp(t *testing.T) {
   335  	t.Run("Default", func(t *testing.T) {
   336  		_, settingsManager := fixtures(nil)
   337  		h, err := settingsManager.GetHelp()
   338  		assert.NoError(t, err)
   339  		assert.Empty(t, h.ChatURL)
   340  		assert.Equal(t, "Chat now!", h.ChatText)
   341  
   342  	})
   343  	t.Run("Set", func(t *testing.T) {
   344  		_, settingsManager := fixtures(map[string]string{
   345  			"help.chatUrl":  "foo",
   346  			"help.chatText": "bar",
   347  		})
   348  		h, err := settingsManager.GetHelp()
   349  		assert.NoError(t, err)
   350  		assert.Equal(t, "foo", h.ChatURL)
   351  		assert.Equal(t, "bar", h.ChatText)
   352  	})
   353  }
   354  
   355  func TestGetOIDCConfig(t *testing.T) {
   356  	kubeClient := fake.NewSimpleClientset(
   357  		&v1.ConfigMap{
   358  			ObjectMeta: metav1.ObjectMeta{
   359  				Name:      common.ArgoCDConfigMapName,
   360  				Namespace: "default",
   361  				Labels: map[string]string{
   362  					"app.kubernetes.io/part-of": "argocd",
   363  				},
   364  			},
   365  			Data: map[string]string{
   366  				"oidc.config": "\n  requestedIDTokenClaims: {\"groups\": {\"essential\": true}}\n",
   367  			},
   368  		},
   369  		&v1.Secret{
   370  			ObjectMeta: metav1.ObjectMeta{
   371  				Name:      common.ArgoCDSecretName,
   372  				Namespace: "default",
   373  				Labels: map[string]string{
   374  					"app.kubernetes.io/part-of": "argocd",
   375  				},
   376  			},
   377  			Data: map[string][]byte{
   378  				"admin.password":   nil,
   379  				"server.secretkey": nil,
   380  			},
   381  		},
   382  	)
   383  	settingsManager := NewSettingsManager(context.Background(), kubeClient, "default")
   384  	settings, err := settingsManager.GetSettings()
   385  	assert.NoError(t, err)
   386  
   387  	oidcConfig := settings.OIDCConfig()
   388  	assert.NotNil(t, oidcConfig)
   389  
   390  	claim := oidcConfig.RequestedIDTokenClaims["groups"]
   391  	assert.NotNil(t, claim)
   392  	assert.Equal(t, true, claim.Essential)
   393  }
   394  
   395  func TestRedirectURL(t *testing.T) {
   396  	cases := map[string][]string{
   397  		"https://localhost:4000":         {"https://localhost:4000/auth/callback", "https://localhost:4000/api/dex/callback"},
   398  		"https://localhost:4000/":        {"https://localhost:4000/auth/callback", "https://localhost:4000/api/dex/callback"},
   399  		"https://localhost:4000/argocd":  {"https://localhost:4000/argocd/auth/callback", "https://localhost:4000/argocd/api/dex/callback"},
   400  		"https://localhost:4000/argocd/": {"https://localhost:4000/argocd/auth/callback", "https://localhost:4000/argocd/api/dex/callback"},
   401  	}
   402  	for given, expected := range cases {
   403  		settings := ArgoCDSettings{URL: given}
   404  		redirectURL, err := settings.RedirectURL()
   405  		assert.NoError(t, err)
   406  		assert.Equal(t, expected[0], redirectURL)
   407  		dexRedirectURL, err := settings.DexRedirectURL()
   408  		assert.NoError(t, err)
   409  		assert.Equal(t, expected[1], dexRedirectURL)
   410  	}
   411  }
   412  
   413  func Test_validateExternalURL(t *testing.T) {
   414  	tests := []struct {
   415  		name   string
   416  		url    string
   417  		errMsg string
   418  	}{
   419  		{name: "Valid URL", url: "https://my.domain.com"},
   420  		{name: "No URL - Valid", url: ""},
   421  		{name: "Invalid URL", url: "my.domain.com", errMsg: "URL must include http or https protocol"},
   422  	}
   423  	for _, tt := range tests {
   424  		t.Run(tt.name, func(t *testing.T) {
   425  			err := validateExternalURL(tt.url)
   426  			if tt.errMsg != "" {
   427  				assert.EqualError(t, err, tt.errMsg)
   428  			} else {
   429  				assert.NoError(t, err)
   430  			}
   431  		})
   432  	}
   433  }