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 }