setConfig applies the given configuration to the alertmanager for `userID`, creating an alertmanager if it doesn't already exist.
(cfg alertspb.AlertConfigDesc)
| 888 | // setConfig applies the given configuration to the alertmanager for `userID`, |
| 889 | // creating an alertmanager if it doesn't already exist. |
| 890 | func (am *MultitenantAlertmanager) setConfig(cfg alertspb.AlertConfigDesc) error { |
| 891 | var userAmConfig *amconfig.Config |
| 892 | var err error |
| 893 | var hasTemplateChanges bool |
| 894 | var userTemplateDir = filepath.Join(am.getTenantDirectory(cfg.User), templatesDir) |
| 895 | var pathsToRemove = make(map[string]struct{}) |
| 896 | |
| 897 | // List existing files to keep track the ones to be removed |
| 898 | if oldTemplateFiles, err := os.ReadDir(userTemplateDir); err == nil { |
| 899 | for _, file := range oldTemplateFiles { |
| 900 | pathToRemove, err := safeTemplateFilepath(userTemplateDir, file.Name()) |
| 901 | if err != nil { |
| 902 | return err |
| 903 | } |
| 904 | level.Debug(am.logger).Log("msg", "discovered existing file", "oldTemplateFile", file.Name(), "pathToRemove", pathToRemove, "user", cfg.User) |
| 905 | pathsToRemove[pathToRemove] = struct{}{} |
| 906 | } |
| 907 | } |
| 908 | |
| 909 | for _, tmpl := range cfg.Templates { |
| 910 | templateFilePath, err := safeTemplateFilepath(userTemplateDir, tmpl.Filename) |
| 911 | level.Debug(am.logger).Log("msg", "skipping template file since it's still used by the config", "file", templateFilePath, "user", cfg.User) |
| 912 | if err != nil { |
| 913 | return err |
| 914 | } |
| 915 | |
| 916 | // Removing from pathsToRemove map the files that still exists in the config |
| 917 | delete(pathsToRemove, templateFilePath) |
| 918 | hasChanged, err := storeTemplateFile(templateFilePath, tmpl.Body) |
| 919 | if err != nil { |
| 920 | return err |
| 921 | } |
| 922 | |
| 923 | if hasChanged { |
| 924 | hasTemplateChanges = true |
| 925 | level.Debug(am.logger).Log("msg", "template file changed", "file", templateFilePath, "body", tmpl.Body, "user", cfg.User) |
| 926 | } |
| 927 | } |
| 928 | |
| 929 | for pathToRemove := range pathsToRemove { |
| 930 | level.Debug(am.logger).Log("msg", "removing stale template file", "file", pathToRemove, "user", cfg.User) |
| 931 | err := os.Remove(pathToRemove) |
| 932 | if err != nil { |
| 933 | level.Warn(am.logger).Log("msg", "failed to remove file", "file", pathToRemove, "err", err) |
| 934 | } |
| 935 | hasTemplateChanges = true |
| 936 | } |
| 937 | |
| 938 | level.Debug(am.logger).Log("msg", "setting config", "user", cfg.User) |
| 939 | |
| 940 | am.alertmanagersMtx.Lock() |
| 941 | defer am.alertmanagersMtx.Unlock() |
| 942 | existing, hasExisting := am.alertmanagers[cfg.User] |
| 943 | |
| 944 | rawCfg := cfg.RawConfig |
| 945 | if cfg.RawConfig == "" { |
| 946 | if am.fallbackConfig == "" { |
| 947 | return fmt.Errorf("blank Alertmanager configuration for %v", cfg.User) |
no test coverage detected