1package setting 2 3import ( 4 "bufio" 5 "math/rand" 6 "net/url" 7 "os" 8 "path" 9 "path/filepath" 10 "runtime" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 18 "gopkg.in/ini.v1" 19) 20 21const ( 22 windows = "windows" 23) 24 25func TestLoadingSettings(t *testing.T) { 26 skipStaticRootValidation = true 27 28 t.Run("Given the default ini files", func(t *testing.T) { 29 cfg := NewCfg() 30 err := cfg.Load(CommandLineArgs{HomePath: "../../", Config: "../../conf/defaults.ini"}) 31 require.Nil(t, err) 32 33 require.Equal(t, "admin", cfg.AdminUser) 34 require.Equal(t, "http://localhost:3000/", cfg.RendererCallbackUrl) 35 }) 36 37 t.Run("default.ini should have no semi-colon commented entries", func(t *testing.T) { 38 file, err := os.Open("../../conf/defaults.ini") 39 if err != nil { 40 t.Errorf("failed to load defaults.ini file: %v", err) 41 } 42 defer func() { 43 err := file.Close() 44 require.Nil(t, err) 45 }() 46 47 scanner := bufio.NewScanner(file) 48 for scanner.Scan() { 49 // This only catches values commented out with ";" and will not catch those that are commented out with "#". 50 if strings.HasPrefix(scanner.Text(), ";") { 51 t.Errorf("entries in defaults.ini must not be commented or environment variables will not work: %v", scanner.Text()) 52 } 53 } 54 }) 55 56 t.Run("sample.ini should load successfully", func(t *testing.T) { 57 customInitPath := CustomInitPath 58 CustomInitPath = "conf/sample.ini" 59 cfg := NewCfg() 60 err := cfg.Load(CommandLineArgs{HomePath: "../../"}) 61 require.Nil(t, err) 62 // Restore CustomInitPath to avoid side effects. 63 CustomInitPath = customInitPath 64 }) 65 66 t.Run("Should be able to override via environment variables", func(t *testing.T) { 67 err := os.Setenv("GF_SECURITY_ADMIN_USER", "superduper") 68 require.NoError(t, err) 69 70 cfg := NewCfg() 71 err = cfg.Load(CommandLineArgs{HomePath: "../../"}) 72 require.Nil(t, err) 73 74 require.Equal(t, "superduper", cfg.AdminUser) 75 require.Equal(t, filepath.Join(HomePath, "data"), cfg.DataPath) 76 require.Equal(t, filepath.Join(cfg.DataPath, "log"), cfg.LogsPath) 77 }) 78 79 t.Run("Should replace password when defined in environment", func(t *testing.T) { 80 err := os.Setenv("GF_SECURITY_ADMIN_PASSWORD", "supersecret") 81 require.NoError(t, err) 82 83 cfg := NewCfg() 84 err = cfg.Load(CommandLineArgs{HomePath: "../../"}) 85 require.Nil(t, err) 86 87 require.Contains(t, appliedEnvOverrides, "GF_SECURITY_ADMIN_PASSWORD=*********") 88 }) 89 90 t.Run("Should replace password in URL when url environment is defined", func(t *testing.T) { 91 err := os.Setenv("GF_DATABASE_URL", "mysql://user:secret@localhost:3306/database") 92 require.NoError(t, err) 93 94 cfg := NewCfg() 95 err = cfg.Load(CommandLineArgs{HomePath: "../../"}) 96 require.Nil(t, err) 97 98 require.Contains(t, appliedEnvOverrides, "GF_DATABASE_URL=mysql://user:xxxxx@localhost:3306/database") 99 }) 100 101 t.Run("Should get property map from command line args array", func(t *testing.T) { 102 cfg := NewCfg() 103 props := cfg.getCommandLineProperties([]string{"cfg:test=value", "cfg:map.test=1"}) 104 105 require.Equal(t, 2, len(props)) 106 require.Equal(t, "value", props["test"]) 107 require.Equal(t, "1", props["map.test"]) 108 }) 109 110 t.Run("Should be able to override via command line", func(t *testing.T) { 111 if runtime.GOOS == windows { 112 cfg := NewCfg() 113 err := cfg.Load(CommandLineArgs{ 114 HomePath: "../../", 115 Args: []string{`cfg:paths.data=c:\tmp\data`, `cfg:paths.logs=c:\tmp\logs`}, 116 }) 117 require.Nil(t, err) 118 require.Equal(t, `c:\tmp\data`, cfg.DataPath) 119 require.Equal(t, `c:\tmp\logs`, cfg.LogsPath) 120 } else { 121 cfg := NewCfg() 122 err := cfg.Load(CommandLineArgs{ 123 HomePath: "../../", 124 Args: []string{"cfg:paths.data=/tmp/data", "cfg:paths.logs=/tmp/logs"}, 125 }) 126 require.Nil(t, err) 127 128 require.Equal(t, "/tmp/data", cfg.DataPath) 129 require.Equal(t, "/tmp/logs", cfg.LogsPath) 130 } 131 }) 132 133 t.Run("Should be able to override defaults via command line", func(t *testing.T) { 134 cfg := NewCfg() 135 err := cfg.Load(CommandLineArgs{ 136 HomePath: "../../", 137 Args: []string{ 138 "cfg:default.server.domain=test2", 139 }, 140 Config: filepath.Join(HomePath, "pkg/setting/testdata/override.ini"), 141 }) 142 require.Nil(t, err) 143 144 require.Equal(t, "test2", cfg.Domain) 145 }) 146 147 t.Run("Defaults can be overridden in specified config file", func(t *testing.T) { 148 if runtime.GOOS == windows { 149 cfg := NewCfg() 150 err := cfg.Load(CommandLineArgs{ 151 HomePath: "../../", 152 Config: filepath.Join(HomePath, "pkg/setting/testdata/override_windows.ini"), 153 Args: []string{`cfg:default.paths.data=c:\tmp\data`}, 154 }) 155 require.Nil(t, err) 156 157 require.Equal(t, `c:\tmp\override`, cfg.DataPath) 158 } else { 159 cfg := NewCfg() 160 err := cfg.Load(CommandLineArgs{ 161 HomePath: "../../", 162 Config: filepath.Join(HomePath, "pkg/setting/testdata/override.ini"), 163 Args: []string{"cfg:default.paths.data=/tmp/data"}, 164 }) 165 require.Nil(t, err) 166 167 require.Equal(t, "/tmp/override", cfg.DataPath) 168 } 169 }) 170 171 t.Run("Command line overrides specified config file", func(t *testing.T) { 172 if runtime.GOOS == windows { 173 cfg := NewCfg() 174 err := cfg.Load(CommandLineArgs{ 175 HomePath: "../../", 176 Config: filepath.Join(HomePath, "pkg/setting/testdata/override_windows.ini"), 177 Args: []string{`cfg:paths.data=c:\tmp\data`}, 178 }) 179 require.Nil(t, err) 180 181 require.Equal(t, `c:\tmp\data`, cfg.DataPath) 182 } else { 183 cfg := NewCfg() 184 err := cfg.Load(CommandLineArgs{ 185 HomePath: "../../", 186 Config: filepath.Join(HomePath, "pkg/setting/testdata/override.ini"), 187 Args: []string{"cfg:paths.data=/tmp/data"}, 188 }) 189 require.Nil(t, err) 190 191 require.Equal(t, "/tmp/data", cfg.DataPath) 192 } 193 }) 194 195 t.Run("Can use environment variables in config values", func(t *testing.T) { 196 if runtime.GOOS == windows { 197 err := os.Setenv("GF_DATA_PATH", `c:\tmp\env_override`) 198 require.NoError(t, err) 199 cfg := NewCfg() 200 err = cfg.Load(CommandLineArgs{ 201 HomePath: "../../", 202 Args: []string{"cfg:paths.data=${GF_DATA_PATH}"}, 203 }) 204 require.Nil(t, err) 205 206 require.Equal(t, `c:\tmp\env_override`, cfg.DataPath) 207 } else { 208 err := os.Setenv("GF_DATA_PATH", "/tmp/env_override") 209 require.NoError(t, err) 210 cfg := NewCfg() 211 err = cfg.Load(CommandLineArgs{ 212 HomePath: "../../", 213 Args: []string{"cfg:paths.data=${GF_DATA_PATH}"}, 214 }) 215 require.Nil(t, err) 216 217 require.Equal(t, "/tmp/env_override", cfg.DataPath) 218 } 219 }) 220 221 t.Run("instance_name default to hostname even if hostname env is empty", func(t *testing.T) { 222 cfg := NewCfg() 223 err := cfg.Load(CommandLineArgs{ 224 HomePath: "../../", 225 }) 226 require.Nil(t, err) 227 228 hostname, err := os.Hostname() 229 require.Nil(t, err) 230 require.Equal(t, hostname, InstanceName) 231 }) 232 233 t.Run("Reading callback_url should add trailing slash", func(t *testing.T) { 234 cfg := NewCfg() 235 err := cfg.Load(CommandLineArgs{ 236 HomePath: "../../", 237 Args: []string{"cfg:rendering.callback_url=http://myserver/renderer"}, 238 }) 239 require.Nil(t, err) 240 241 require.Equal(t, "http://myserver/renderer/", cfg.RendererCallbackUrl) 242 }) 243 244 t.Run("Only sync_ttl should return the value sync_ttl", func(t *testing.T) { 245 cfg := NewCfg() 246 err := cfg.Load(CommandLineArgs{ 247 HomePath: "../../", 248 Args: []string{"cfg:auth.proxy.sync_ttl=2"}, 249 }) 250 require.Nil(t, err) 251 252 require.Equal(t, 2, cfg.AuthProxySyncTTL) 253 }) 254 255 t.Run("Only ldap_sync_ttl should return the value ldap_sync_ttl", func(t *testing.T) { 256 cfg := NewCfg() 257 err := cfg.Load(CommandLineArgs{ 258 HomePath: "../../", 259 Args: []string{"cfg:auth.proxy.ldap_sync_ttl=5"}, 260 }) 261 require.Nil(t, err) 262 263 require.Equal(t, 5, cfg.AuthProxySyncTTL) 264 }) 265 266 t.Run("ldap_sync should override ldap_sync_ttl that is default value", func(t *testing.T) { 267 cfg := NewCfg() 268 err := cfg.Load(CommandLineArgs{ 269 HomePath: "../../", 270 Args: []string{"cfg:auth.proxy.sync_ttl=5"}, 271 }) 272 require.Nil(t, err) 273 274 require.Equal(t, 5, cfg.AuthProxySyncTTL) 275 }) 276 277 t.Run("ldap_sync should not override ldap_sync_ttl that is different from default value", func(t *testing.T) { 278 cfg := NewCfg() 279 err := cfg.Load(CommandLineArgs{ 280 HomePath: "../../", 281 Args: []string{"cfg:auth.proxy.ldap_sync_ttl=12", "cfg:auth.proxy.sync_ttl=5"}, 282 }) 283 require.Nil(t, err) 284 285 require.Equal(t, 12, cfg.AuthProxySyncTTL) 286 }) 287 288 t.Run("Test reading string values from .ini file", func(t *testing.T) { 289 iniFile, err := ini.Load(path.Join(HomePath, "pkg/setting/testdata/invalid.ini")) 290 require.Nil(t, err) 291 292 t.Run("If key is found - should return value from ini file", func(t *testing.T) { 293 value := valueAsString(iniFile.Section("server"), "alt_url", "") 294 require.Equal(t, "https://grafana.com/", value) 295 }) 296 297 t.Run("If key is not found - should return default value", func(t *testing.T) { 298 value := valueAsString(iniFile.Section("server"), "extra_url", "default_url_val") 299 require.Equal(t, "default_url_val", value) 300 }) 301 }) 302} 303 304func TestParseAppURLAndSubURL(t *testing.T) { 305 testCases := []struct { 306 rootURL string 307 expectedAppURL string 308 expectedAppSubURL string 309 }{ 310 {rootURL: "http://localhost:3000/", expectedAppURL: "http://localhost:3000/"}, 311 {rootURL: "http://localhost:3000", expectedAppURL: "http://localhost:3000/"}, 312 {rootURL: "http://localhost:3000/grafana", expectedAppURL: "http://localhost:3000/grafana/", expectedAppSubURL: "/grafana"}, 313 {rootURL: "http://localhost:3000/grafana/", expectedAppURL: "http://localhost:3000/grafana/", expectedAppSubURL: "/grafana"}, 314 } 315 316 for _, tc := range testCases { 317 f := ini.Empty() 318 cfg := NewCfg() 319 s, err := f.NewSection("server") 320 require.NoError(t, err) 321 _, err = s.NewKey("root_url", tc.rootURL) 322 require.NoError(t, err) 323 appURL, appSubURL, err := cfg.parseAppUrlAndSubUrl(s) 324 require.NoError(t, err) 325 require.Equal(t, tc.expectedAppURL, appURL) 326 require.Equal(t, tc.expectedAppSubURL, appSubURL) 327 } 328} 329 330func TestAuthDurationSettings(t *testing.T) { 331 const maxInactiveDaysTest = 240 * time.Hour 332 333 f := ini.Empty() 334 cfg := NewCfg() 335 sec, err := f.NewSection("auth") 336 require.NoError(t, err) 337 _, err = sec.NewKey("login_maximum_inactive_lifetime_days", "10") 338 require.NoError(t, err) 339 _, err = sec.NewKey("login_maximum_inactive_lifetime_duration", "") 340 require.NoError(t, err) 341 err = readAuthSettings(f, cfg) 342 require.NoError(t, err) 343 require.Equal(t, maxInactiveDaysTest, cfg.LoginMaxInactiveLifetime) 344 345 f = ini.Empty() 346 sec, err = f.NewSection("auth") 347 require.NoError(t, err) 348 _, err = sec.NewKey("login_maximum_inactive_lifetime_duration", "824h") 349 require.NoError(t, err) 350 maxInactiveDurationTest, err := time.ParseDuration("824h") 351 require.NoError(t, err) 352 err = readAuthSettings(f, cfg) 353 require.NoError(t, err) 354 require.Equal(t, maxInactiveDurationTest, cfg.LoginMaxInactiveLifetime) 355 356 f = ini.Empty() 357 sec, err = f.NewSection("auth") 358 require.NoError(t, err) 359 _, err = sec.NewKey("login_maximum_lifetime_days", "24") 360 require.NoError(t, err) 361 _, err = sec.NewKey("login_maximum_lifetime_duration", "") 362 require.NoError(t, err) 363 maxLifetimeDaysTest, err := time.ParseDuration("576h") 364 require.NoError(t, err) 365 err = readAuthSettings(f, cfg) 366 require.NoError(t, err) 367 require.Equal(t, maxLifetimeDaysTest, cfg.LoginMaxLifetime) 368 369 f = ini.Empty() 370 sec, err = f.NewSection("auth") 371 require.NoError(t, err) 372 _, err = sec.NewKey("login_maximum_lifetime_duration", "824h") 373 require.NoError(t, err) 374 maxLifetimeDurationTest, err := time.ParseDuration("824h") 375 require.NoError(t, err) 376 err = readAuthSettings(f, cfg) 377 require.NoError(t, err) 378 require.Equal(t, maxLifetimeDurationTest, cfg.LoginMaxLifetime) 379 380 f = ini.Empty() 381 sec, err = f.NewSection("auth") 382 require.NoError(t, err) 383 _, err = sec.NewKey("login_maximum_lifetime_days", "") 384 require.NoError(t, err) 385 _, err = sec.NewKey("login_maximum_lifetime_duration", "") 386 require.NoError(t, err) 387 maxLifetimeDurationTest, err = time.ParseDuration("720h") 388 require.NoError(t, err) 389 err = readAuthSettings(f, cfg) 390 require.NoError(t, err) 391 require.Equal(t, maxLifetimeDurationTest, cfg.LoginMaxLifetime) 392} 393 394func TestGetCDNPath(t *testing.T) { 395 var err error 396 cfg := NewCfg() 397 cfg.BuildVersion = "v7.5.0-11124" 398 cfg.CDNRootURL, err = url.Parse("http://cdn.grafana.com") 399 require.NoError(t, err) 400 401 require.Equal(t, "http://cdn.grafana.com/grafana-oss/v7.5.0-11124/", cfg.GetContentDeliveryURL("grafana-oss")) 402 require.Equal(t, "http://cdn.grafana.com/grafana/v7.5.0-11124/", cfg.GetContentDeliveryURL("grafana")) 403} 404 405func TestGetContentDeliveryURLWhenNoCDNRootURLIsSet(t *testing.T) { 406 cfg := NewCfg() 407 require.Equal(t, "", cfg.GetContentDeliveryURL("grafana-oss")) 408} 409 410func TestGetCDNPathWithPreReleaseVersionAndSubPath(t *testing.T) { 411 var err error 412 cfg := NewCfg() 413 cfg.BuildVersion = "v7.5.0-11124pre" 414 cfg.CDNRootURL, err = url.Parse("http://cdn.grafana.com/sub") 415 require.NoError(t, err) 416 require.Equal(t, "http://cdn.grafana.com/sub/grafana-oss/v7.5.0-11124pre/", cfg.GetContentDeliveryURL("grafana-oss")) 417 require.Equal(t, "http://cdn.grafana.com/sub/grafana/v7.5.0-11124pre/", cfg.GetContentDeliveryURL("grafana")) 418} 419 420// Adding a case for this in case we switch to proper semver version strings 421func TestGetCDNPathWithAlphaVersion(t *testing.T) { 422 var err error 423 cfg := NewCfg() 424 cfg.BuildVersion = "v7.5.0-alpha.11124" 425 cfg.CDNRootURL, err = url.Parse("http://cdn.grafana.com") 426 require.NoError(t, err) 427 require.Equal(t, "http://cdn.grafana.com/grafana-oss/v7.5.0-alpha.11124/", cfg.GetContentDeliveryURL("grafana-oss")) 428 require.Equal(t, "http://cdn.grafana.com/grafana/v7.5.0-alpha.11124/", cfg.GetContentDeliveryURL("grafana")) 429} 430 431func TestAlertingEnabled(t *testing.T) { 432 anyBoolean := func() bool { 433 return rand.Int63()%2 == 0 434 } 435 436 testCases := []struct { 437 desc string 438 unifiedAlertingEnabled string 439 legacyAlertingEnabled string 440 featureToggleSet bool 441 isEnterprise bool 442 verifyCfg func(*testing.T, Cfg, *ini.File) 443 }{ 444 { 445 desc: "when legacy alerting is enabled and unified is disabled", 446 legacyAlertingEnabled: "true", 447 unifiedAlertingEnabled: "false", 448 isEnterprise: anyBoolean(), 449 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 450 err := readAlertingSettings(f) 451 require.NoError(t, err) 452 err = cfg.readFeatureToggles(f) 453 require.NoError(t, err) 454 err = cfg.ReadUnifiedAlertingSettings(f) 455 require.NoError(t, err) 456 assert.NotNil(t, cfg.UnifiedAlerting.Enabled) 457 assert.Equal(t, *cfg.UnifiedAlerting.Enabled, false) 458 assert.NotNil(t, AlertingEnabled) 459 assert.Equal(t, *AlertingEnabled, true) 460 }, 461 }, 462 { 463 desc: "when legacy alerting is disabled and unified is enabled", 464 legacyAlertingEnabled: "false", 465 unifiedAlertingEnabled: "true", 466 isEnterprise: anyBoolean(), 467 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 468 err := readAlertingSettings(f) 469 require.NoError(t, err) 470 err = cfg.readFeatureToggles(f) 471 require.NoError(t, err) 472 err = cfg.ReadUnifiedAlertingSettings(f) 473 require.NoError(t, err) 474 assert.NotNil(t, cfg.UnifiedAlerting.Enabled) 475 assert.Equal(t, *cfg.UnifiedAlerting.Enabled, true) 476 assert.NotNil(t, AlertingEnabled) 477 assert.Equal(t, *AlertingEnabled, false) 478 }, 479 }, 480 { 481 desc: "when both alerting are enabled", 482 legacyAlertingEnabled: "true", 483 unifiedAlertingEnabled: "true", 484 isEnterprise: anyBoolean(), 485 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 486 err := readAlertingSettings(f) 487 require.NoError(t, err) 488 err = cfg.readFeatureToggles(f) 489 require.NoError(t, err) 490 err = cfg.ReadUnifiedAlertingSettings(f) 491 require.Error(t, err) 492 }, 493 }, 494 { 495 desc: "when legacy alerting is invalid (or not defined) and unified is disabled", 496 legacyAlertingEnabled: "", 497 unifiedAlertingEnabled: "false", 498 isEnterprise: anyBoolean(), 499 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 500 err := readAlertingSettings(f) 501 require.NoError(t, err) 502 err = cfg.readFeatureToggles(f) 503 require.NoError(t, err) 504 err = cfg.ReadUnifiedAlertingSettings(f) 505 require.NoError(t, err) 506 assert.NotNil(t, cfg.UnifiedAlerting.Enabled) 507 assert.Equal(t, *cfg.UnifiedAlerting.Enabled, false) 508 assert.NotNil(t, AlertingEnabled) 509 assert.Equal(t, *AlertingEnabled, true) 510 }, 511 }, 512 { 513 desc: "when legacy alerting is invalid (or not defined) and unified is enabled", 514 legacyAlertingEnabled: "", 515 unifiedAlertingEnabled: "true", 516 isEnterprise: anyBoolean(), 517 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 518 err := readAlertingSettings(f) 519 require.NoError(t, err) 520 err = cfg.readFeatureToggles(f) 521 require.NoError(t, err) 522 err = cfg.ReadUnifiedAlertingSettings(f) 523 require.NoError(t, err) 524 assert.NotNil(t, cfg.UnifiedAlerting.Enabled) 525 assert.Equal(t, *cfg.UnifiedAlerting.Enabled, true) 526 assert.NotNil(t, AlertingEnabled) 527 assert.Equal(t, *AlertingEnabled, false) 528 }, 529 }, 530 { 531 desc: "when legacy alerting is enabled and unified is invalid (or not defined) [OSS]", 532 legacyAlertingEnabled: "true", 533 unifiedAlertingEnabled: "", 534 isEnterprise: false, 535 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 536 err := readAlertingSettings(f) 537 require.NoError(t, err) 538 err = cfg.readFeatureToggles(f) 539 require.NoError(t, err) 540 err = cfg.ReadUnifiedAlertingSettings(f) 541 require.NoError(t, err) 542 assert.Nil(t, cfg.UnifiedAlerting.Enabled) 543 assert.NotNil(t, AlertingEnabled) 544 assert.Equal(t, *AlertingEnabled, true) 545 }, 546 }, 547 { 548 desc: "when legacy alerting is enabled and unified is invalid (or not defined) [Enterprise]", 549 legacyAlertingEnabled: "true", 550 unifiedAlertingEnabled: "", 551 isEnterprise: true, 552 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 553 err := readAlertingSettings(f) 554 require.NoError(t, err) 555 err = cfg.readFeatureToggles(f) 556 require.NoError(t, err) 557 err = cfg.ReadUnifiedAlertingSettings(f) 558 require.NoError(t, err) 559 assert.NotNil(t, cfg.UnifiedAlerting.Enabled) 560 assert.Equal(t, *cfg.UnifiedAlerting.Enabled, false) 561 assert.NotNil(t, AlertingEnabled) 562 assert.Equal(t, *AlertingEnabled, true) 563 }, 564 }, 565 { 566 desc: "when legacy alerting is disabled and unified is invalid (or not defined) [OSS]", 567 legacyAlertingEnabled: "false", 568 unifiedAlertingEnabled: "invalid", 569 isEnterprise: false, 570 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 571 err := readAlertingSettings(f) 572 require.NoError(t, err) 573 err = cfg.readFeatureToggles(f) 574 require.NoError(t, err) 575 err = cfg.ReadUnifiedAlertingSettings(f) 576 require.NoError(t, err) 577 assert.NotNil(t, cfg.UnifiedAlerting.Enabled) 578 assert.Equal(t, *cfg.UnifiedAlerting.Enabled, true) 579 assert.NotNil(t, AlertingEnabled) 580 assert.Equal(t, *AlertingEnabled, false) 581 }, 582 }, 583 { 584 desc: "when legacy alerting is disabled and unified is invalid (or not defined) [Enterprise]", 585 legacyAlertingEnabled: "false", 586 unifiedAlertingEnabled: "invalid", 587 isEnterprise: true, 588 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 589 err := readAlertingSettings(f) 590 require.NoError(t, err) 591 err = cfg.readFeatureToggles(f) 592 require.NoError(t, err) 593 err = cfg.ReadUnifiedAlertingSettings(f) 594 require.NoError(t, err) 595 assert.NotNil(t, cfg.UnifiedAlerting.Enabled) 596 assert.Equal(t, *cfg.UnifiedAlerting.Enabled, false) 597 assert.NotNil(t, AlertingEnabled) 598 assert.Equal(t, *AlertingEnabled, false) 599 }, 600 }, 601 { 602 desc: "when both are invalid (or not defined) [OSS]", 603 legacyAlertingEnabled: "invalid", 604 unifiedAlertingEnabled: "invalid", 605 isEnterprise: false, 606 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 607 err := readAlertingSettings(f) 608 require.NoError(t, err) 609 err = cfg.readFeatureToggles(f) 610 require.NoError(t, err) 611 err = cfg.ReadUnifiedAlertingSettings(f) 612 require.NoError(t, err) 613 assert.Nil(t, cfg.UnifiedAlerting.Enabled) 614 assert.Nil(t, AlertingEnabled) 615 }, 616 }, 617 { 618 desc: "when both are invalid (or not defined) [Enterprise]", 619 legacyAlertingEnabled: "invalid", 620 unifiedAlertingEnabled: "invalid", 621 isEnterprise: true, 622 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 623 err := readAlertingSettings(f) 624 require.NoError(t, err) 625 err = cfg.readFeatureToggles(f) 626 require.NoError(t, err) 627 err = cfg.ReadUnifiedAlertingSettings(f) 628 require.NoError(t, err) 629 assert.NotNil(t, cfg.UnifiedAlerting.Enabled) 630 assert.Equal(t, *cfg.UnifiedAlerting.Enabled, false) 631 assert.NotNil(t, AlertingEnabled) 632 assert.Equal(t, *AlertingEnabled, true) 633 }, 634 }, 635 { 636 desc: "when both are false", 637 legacyAlertingEnabled: "false", 638 unifiedAlertingEnabled: "false", 639 isEnterprise: anyBoolean(), 640 verifyCfg: func(t *testing.T, cfg Cfg, f *ini.File) { 641 err := readAlertingSettings(f) 642 require.NoError(t, err) 643 err = cfg.readFeatureToggles(f) 644 require.NoError(t, err) 645 err = cfg.ReadUnifiedAlertingSettings(f) 646 require.NoError(t, err) 647 assert.NotNil(t, cfg.UnifiedAlerting.Enabled) 648 assert.Equal(t, *cfg.UnifiedAlerting.Enabled, false) 649 assert.NotNil(t, AlertingEnabled) 650 assert.Equal(t, *AlertingEnabled, false) 651 }, 652 }, 653 } 654 655 var isEnterpriseOld = IsEnterprise 656 t.Cleanup(func() { 657 IsEnterprise = isEnterpriseOld 658 }) 659 660 for _, tc := range testCases { 661 t.Run(tc.desc, func(t *testing.T) { 662 IsEnterprise = tc.isEnterprise 663 t.Cleanup(func() { 664 AlertingEnabled = nil 665 }) 666 667 f := ini.Empty() 668 cfg := NewCfg() 669 unifiedAlertingSec, err := f.NewSection("unified_alerting") 670 require.NoError(t, err) 671 _, err = unifiedAlertingSec.NewKey("enabled", tc.unifiedAlertingEnabled) 672 require.NoError(t, err) 673 674 alertingSec, err := f.NewSection("alerting") 675 require.NoError(t, err) 676 _, err = alertingSec.NewKey("enabled", tc.legacyAlertingEnabled) 677 require.NoError(t, err) 678 679 tc.verifyCfg(t, *cfg, f) 680 }) 681 } 682} 683