From cfb3ab52a303e6b0041508e08f80e2d5e579c970 Mon Sep 17 00:00:00 2001 From: Wing924 Date: Wed, 26 Feb 2020 19:58:50 +0900 Subject: [PATCH 01/12] Added flags to disable Alertmanager notifications methods. Signed-off-by: Wing924 --- CHANGELOG.md | 11 +++++- pkg/configs/api/api.go | 70 +++++++++++++++++++++++++++++---- pkg/configs/api/api_test.go | 15 ++++++- pkg/configs/api/helpers_test.go | 6 ++- pkg/cortex/cortex.go | 2 + pkg/cortex/modules.go | 2 +- 6 files changed, 94 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41a403e54e2..a4ebf06ea1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,8 +29,17 @@ * `--experimental.distributor.user-subring-size` * [FEATURE] Added flag `-experimental.ruler.enable-api` to enable the ruler api which implements the Prometheus API `/api/v1/rules` and `/api/v1/alerts` endpoints under the configured `-http.prefix`. #1999 * [FEATURE] Added sharding support to compactor when using the experimental TSDB blocks storage. #2113 -* [FEATURE] Add ability to override YAML config file settings using environment variables. #2147 +* [FEATURE] Added ability to override YAML config file settings using environment variables. #2147 * `-config.expand-env` +* [FEATURE] Added flags to disable Alertmanager notifications methods. + * `-configs-api.notifications.disable-email` + * `-configs-api.notifications.disable-pagerduty` + * `-configs-api.notifications.disable-pushover` + * `-configs-api.notifications.disable-slack` + * `-configs-api.notifications.disable-opsgenie` + * `-configs-api.notifications.disable-webhook` + * `-configs-api.notifications.disable-victorops` + * `-configs-api.notifications.disable-wechat` * [FEATURE] Add /config HTTP endpoint which exposes the current Cortex configuration as YAML. #2165 * [ENHANCEMENT] Add `status` label to `cortex_alertmanager_configs` metric to gauge the number of valid and invalid configs. #2125 * [ENHANCEMENT] Cassandra Authentication: added the `custom_authenticators` config option that allows users to authenticate with cassandra clusters using password authenticators that are not approved by default in [gocql](https://github.com/gocql/gocql/blob/81b8263d9fe526782a588ef94d3fa5c6148e5d67/conn.go#L27) #2093 diff --git a/pkg/configs/api/api.go b/pkg/configs/api/api.go index 88bb30ad418..3885499c4cd 100644 --- a/pkg/configs/api/api.go +++ b/pkg/configs/api/api.go @@ -3,6 +3,7 @@ package api import ( "database/sql" "encoding/json" + "flag" "fmt" "html/template" "io/ioutil" @@ -19,15 +20,47 @@ import ( "github.com/cortexproject/cortex/pkg/util" ) +type Config struct { + Notifications NotificationsConfig `yaml:"notifications"` +} + +type NotificationsConfig struct { + DisableEmail bool `yaml:"allow_email"` + DisablePagerDuty bool `yaml:"allow_pagerduty"` + DisablePushover bool `yaml:"allow_pushover"` + DisableSlack bool `yaml:"allow_slack"` + DisableOpsGenie bool `yaml:"allow_opsgenie"` + DisableWebHook bool `yaml:"allow_webhook"` + DisableVictorOps bool `yaml:"allow_victorops"` + DisableWeChat bool `yaml:"allow_wechat"` + // Hipchat has reached end of life and is no longer available +} + +// RegisterFlagsWithPrefix adds the flags required to config this to the given FlagSet +func (cfg *Config) RegisterFlags(f *flag.FlagSet) { + f.BoolVar(&cfg.Notifications.DisableEmail, "configs-api.notifications.disable-email", false, "Disable Email notifications for Alertmanager.") + f.BoolVar(&cfg.Notifications.DisablePagerDuty, "configs-api.notifications.disable-pagerduty", false, "Disable PagerDuty notifications for Alertmanager.") + f.BoolVar(&cfg.Notifications.DisablePushover, "configs-api.notifications.disable-pushover", false, "Disable Pushover notifications for Alertmanager.") + f.BoolVar(&cfg.Notifications.DisableSlack, "configs-api.notifications.disable-slack", false, "Disable Slack notifications for Alertmanager.") + f.BoolVar(&cfg.Notifications.DisableOpsGenie, "configs-api.notifications.disable-opsgenie", false, "Disable OpsGenie notifications for Alertmanager.") + f.BoolVar(&cfg.Notifications.DisableWebHook, "configs-api.notifications.disable-webhook", false, "Disable WebHook notifications for Alertmanager.") + f.BoolVar(&cfg.Notifications.DisableVictorOps, "configs-api.notifications.disable-victorops", false, "Disable VictorOps notifications for Alertmanager.") + f.BoolVar(&cfg.Notifications.DisableWeChat, "configs-api.notifications.disable-wechat", false, "Disable WeChat notifications for Alertmanager.") +} + // API implements the configs api. type API struct { - db db.DB http.Handler + db db.DB + cfg Config } // New creates a new API -func New(database db.DB) *API { - a := &API{db: database} +func New(database db.DB, cfg Config) *API { + a := &API{ + db: database, + cfg: cfg, + } r := mux.NewRouter() a.RegisterRoutes(r) a.Handler = r @@ -117,7 +150,7 @@ func (a *API) setConfig(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusBadRequest) return } - if err := validateAlertmanagerConfig(cfg.AlertmanagerConfig); err != nil && cfg.AlertmanagerConfig != "" { + if err := validateAlertmanagerConfig(cfg.AlertmanagerConfig, a.cfg.Notifications); err != nil && cfg.AlertmanagerConfig != "" { level.Error(logger).Log("msg", "invalid Alertmanager config", "err", err) http.Error(w, fmt.Sprintf("Invalid Alertmanager config: %v", err), http.StatusBadRequest) return @@ -150,7 +183,7 @@ func (a *API) validateAlertmanagerConfig(w http.ResponseWriter, r *http.Request) return } - if err = validateAlertmanagerConfig(string(cfg)); err != nil { + if err = validateAlertmanagerConfig(string(cfg), a.cfg.Notifications); err != nil { w.WriteHeader(http.StatusBadRequest) util.WriteJSONResponse(w, map[string]string{ "status": "error", @@ -164,15 +197,36 @@ func (a *API) validateAlertmanagerConfig(w http.ResponseWriter, r *http.Request) }) } -func validateAlertmanagerConfig(cfg string) error { +func validateAlertmanagerConfig(cfg string, noCfg NotificationsConfig) error { amCfg, err := amconfig.Load(cfg) if err != nil { return err } for _, recv := range amCfg.Receivers { - if len(recv.EmailConfigs) != 0 { - return fmt.Errorf("email notifications are not supported in Cortex yet") + if noCfg.DisableEmail && len(recv.EmailConfigs) > 0 { + return fmt.Errorf("email notifications are disabled in Cortex yet") + } + if noCfg.DisablePagerDuty && len(recv.PagerdutyConfigs) > 0 { + return fmt.Errorf("pager-duty notifications are disabled in Cortex yet") + } + if noCfg.DisablePushover && len(recv.PushoverConfigs) > 0 { + return fmt.Errorf("pushover notifications are disabled in Cortex yet") + } + if noCfg.DisableSlack && len(recv.SlackConfigs) > 0 { + return fmt.Errorf("slack notifications are disabled in Cortex yet") + } + if noCfg.DisableOpsGenie && len(recv.OpsGenieConfigs) > 0 { + return fmt.Errorf("ops-genie notifications are disabled in Cortex yet") + } + if noCfg.DisableWebHook && len(recv.WebhookConfigs) > 0 { + return fmt.Errorf("web-hook notifications are disabled in Cortex yet") + } + if noCfg.DisableVictorOps && len(recv.VictorOpsConfigs) > 0 { + return fmt.Errorf("victor-ops notifications are disabled in Cortex yet") + } + if noCfg.DisableWeChat && len(recv.WechatConfigs) > 0 { + return fmt.Errorf("we-chat notifications are disabled in Cortex yet") } } diff --git a/pkg/configs/api/api_test.go b/pkg/configs/api/api_test.go index 45abef4d3b6..279d2604324 100644 --- a/pkg/configs/api/api_test.go +++ b/pkg/configs/api/api_test.go @@ -244,7 +244,20 @@ var amCfgValidationTests = []struct { email_configs: - to: myteam@foobar.org`, shouldFail: true, - errContains: "email notifications are not supported in Cortex yet", + errContains: "email notifications are disabled in Cortex yet", + }, { + config: ` + global: + smtp_smarthost: localhost:25 + smtp_from: alertmanager@example.org + route: + receiver: noop + + receivers: + - name: noop + slack_configs: + - api_url: http://slack`, + shouldFail: false, }, } diff --git a/pkg/configs/api/helpers_test.go b/pkg/configs/api/helpers_test.go index 0e0ff739e39..b9cbe1e4230 100644 --- a/pkg/configs/api/helpers_test.go +++ b/pkg/configs/api/helpers_test.go @@ -27,7 +27,11 @@ var ( // setup sets up the environment for the tests. func setup(t *testing.T) { database = dbtest.Setup(t) - app = api.New(database) + app = api.New(database, api.Config{ + Notifications: api.NotificationsConfig{ + DisableEmail: true, + }, + }) counter = 0 } diff --git a/pkg/cortex/cortex.go b/pkg/cortex/cortex.go index b8cc7d2293e..1438d2fc482 100644 --- a/pkg/cortex/cortex.go +++ b/pkg/cortex/cortex.go @@ -81,6 +81,7 @@ type Config struct { Compactor compactor.Config `yaml:"compactor,omitempty" doc:"hidden"` Ruler ruler.Config `yaml:"ruler,omitempty"` + ConfigsAPI api.Config `yaml:"configs_api,omitempty"` ConfigDB db.Config `yaml:"configdb,omitempty"` Alertmanager alertmanager.MultitenantAlertmanagerConfig `yaml:"alertmanager,omitempty"` RuntimeConfig runtimeconfig.ManagerConfig `yaml:"runtime_config,omitempty"` @@ -116,6 +117,7 @@ func (c *Config) RegisterFlags(f *flag.FlagSet) { c.Compactor.RegisterFlags(f) c.Ruler.RegisterFlags(f) + c.ConfigsAPI.RegisterFlags(f) c.ConfigDB.RegisterFlags(f) c.Alertmanager.RegisterFlags(f) c.RuntimeConfig.RegisterFlags(f) diff --git a/pkg/cortex/modules.go b/pkg/cortex/modules.go index f2027efd37a..8b37d2ec23f 100644 --- a/pkg/cortex/modules.go +++ b/pkg/cortex/modules.go @@ -520,7 +520,7 @@ func (t *Cortex) initConfigs(cfg *Config) (err error) { return } - t.configAPI = api.New(t.configDB) + t.configAPI = api.New(t.configDB, cfg.ConfigsAPI) t.configAPI.RegisterRoutes(t.server.HTTP) return } From bba4f81a2f7195e4c88aa36a1fa050d1681002a0 Mon Sep 17 00:00:00 2001 From: Wing924 Date: Wed, 26 Feb 2020 20:03:34 +0900 Subject: [PATCH 02/12] fix Signed-off-by: Wing924 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4ebf06ea1f..eff425a5806 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ * [FEATURE] Added sharding support to compactor when using the experimental TSDB blocks storage. #2113 * [FEATURE] Added ability to override YAML config file settings using environment variables. #2147 * `-config.expand-env` -* [FEATURE] Added flags to disable Alertmanager notifications methods. +* [FEATURE] Added flags to disable Alertmanager notifications methods. #2187 * `-configs-api.notifications.disable-email` * `-configs-api.notifications.disable-pagerduty` * `-configs-api.notifications.disable-pushover` From 61eb461976c8bf719cf00e77727ab53ff3457fa4 Mon Sep 17 00:00:00 2001 From: Wing924 Date: Wed, 26 Feb 2020 20:07:40 +0900 Subject: [PATCH 03/12] add doc Signed-off-by: Wing924 --- docs/configuration/config-file-reference.md | 43 +++++++++++++++++++++ pkg/configs/api/api.go | 2 + tools/doc-generator/main.go | 7 ++++ 3 files changed, 52 insertions(+) diff --git a/docs/configuration/config-file-reference.md b/docs/configuration/config-file-reference.md index 536ef1a5a0f..ddf78590936 100644 --- a/docs/configuration/config-file-reference.md +++ b/docs/configuration/config-file-reference.md @@ -108,6 +108,10 @@ Where default_value is the value to use if the environment variable is undefined # The ruler_config configures the Cortex ruler. [ruler: ] +# The configs_api_config configures the configs API used by the 'configs' +# service to expose APIs to manage them. +[configs_api: ] + # The configdb_config configures the config database storing rules and alerts, # and used by the 'configs' service to expose APIs to manage them. [configdb: ] @@ -2075,6 +2079,45 @@ The `fifo_cache_config` configures the local in-memory cache. [validity: | default = 0s] ``` +## `configs_api_config` + +The `configs_api_config` configures the configs API used by the 'configs' service to expose APIs to manage them. + +```yaml +notifications: + # Disable Email notifications for Alertmanager. + # CLI flag: -configs-api.notifications.disable-email + [allow_email: | default = false] + + # Disable PagerDuty notifications for Alertmanager. + # CLI flag: -configs-api.notifications.disable-pagerduty + [allow_pagerduty: | default = false] + + # Disable Pushover notifications for Alertmanager. + # CLI flag: -configs-api.notifications.disable-pushover + [allow_pushover: | default = false] + + # Disable Slack notifications for Alertmanager. + # CLI flag: -configs-api.notifications.disable-slack + [allow_slack: | default = false] + + # Disable OpsGenie notifications for Alertmanager. + # CLI flag: -configs-api.notifications.disable-opsgenie + [allow_opsgenie: | default = false] + + # Disable WebHook notifications for Alertmanager. + # CLI flag: -configs-api.notifications.disable-webhook + [allow_webhook: | default = false] + + # Disable VictorOps notifications for Alertmanager. + # CLI flag: -configs-api.notifications.disable-victorops + [allow_victorops: | default = false] + + # Disable WeChat notifications for Alertmanager. + # CLI flag: -configs-api.notifications.disable-wechat + [allow_wechat: | default = false] +``` + ## `configdb_config` The `configdb_config` configures the config database storing rules and alerts, and used by the 'configs' service to expose APIs to manage them. diff --git a/pkg/configs/api/api.go b/pkg/configs/api/api.go index 3885499c4cd..1dc34c56e90 100644 --- a/pkg/configs/api/api.go +++ b/pkg/configs/api/api.go @@ -20,10 +20,12 @@ import ( "github.com/cortexproject/cortex/pkg/util" ) +// Config configures the configs API. type Config struct { Notifications NotificationsConfig `yaml:"notifications"` } +// NotificationsConfig configures Alertmanager notifications method. type NotificationsConfig struct { DisableEmail bool `yaml:"allow_email"` DisablePagerDuty bool `yaml:"allow_pagerduty"` diff --git a/tools/doc-generator/main.go b/tools/doc-generator/main.go index c7e7601222d..c49bb3dbabc 100644 --- a/tools/doc-generator/main.go +++ b/tools/doc-generator/main.go @@ -6,6 +6,8 @@ import ( "reflect" "strings" + "github.com/cortexproject/cortex/pkg/configs/api" + "github.com/weaveworks/common/server" "github.com/cortexproject/cortex/pkg/alertmanager" @@ -142,6 +144,11 @@ var ( structType: reflect.TypeOf(cache.FifoCacheConfig{}), desc: "The fifo_cache_config configures the local in-memory cache.", }, + { + name: "configs_api_config", + structType: reflect.TypeOf(api.Config{}), + desc: "The configs_api_config configures the configs API used by the 'configs' service to expose APIs to manage them.", + }, { name: "configdb_config", structType: reflect.TypeOf(db.Config{}), From 13caa80381676345d459d582ac9c296571d19cd1 Mon Sep 17 00:00:00 2001 From: Wing924 Date: Thu, 27 Feb 2020 15:54:23 +0900 Subject: [PATCH 04/12] fix Signed-off-by: Wing924 --- CHANGELOG.md | 12 ++-- docs/configuration/config-file-reference.md | 74 ++++++--------------- pkg/configs/api/api.go | 45 +++---------- pkg/configs/db/db.go | 12 ++-- pkg/cortex/cortex.go | 6 +- pkg/cortex/modules.go | 4 +- tools/doc-generator/main.go | 13 +--- 7 files changed, 45 insertions(+), 121 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9962e3bc2e..a776bb5b674 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ * [CHANGE] Updated Prometheus dependency to v2.16.0. This Prometheus version uses Active Query Tracker to limit concurrent queries. In order to keep `-querier.max-concurrent` working, Active Query Tracker is enabled by default, and is configured to store its data to `active-query-tracker` directory (relative to current directory when Cortex started). This can be changed by using `-querier.active-query-tracker-dir` option. Purpose of Active Query Tracker is to log queries that were running when Cortex crashes. This logging happens on next Cortex start. #2088 * [CHANGE] Experimental TSDB: TSDB head compaction interval and concurrency is now configurable (defaults to 1 min interval and 5 concurrent head compactions). New options: `-experimental.tsdb.head-compaction-interval` and `-experimental.tsdb.head-compaction-concurrency`. #2172 * [CHANGE] Remove fluentd-based billing infrastructure and flags such as `-distributor.enable-billing`. #1491 +* [CHNAGE] Renamed Configs API configuration options. + * `-database.*` -> `-configs.database.*` * [FEATURE] Added a read-only local alertmanager config store using files named corresponding to their tenant id. #2125 * [FEATURE] Added user sub rings to distribute users to a subset of ingesters. #1947 * `--experimental.distributor.user-subring-size` @@ -33,14 +35,8 @@ * [FEATURE] Added ability to override YAML config file settings using environment variables. #2147 * `-config.expand-env` * [FEATURE] Added flags to disable Alertmanager notifications methods. #2187 - * `-configs-api.notifications.disable-email` - * `-configs-api.notifications.disable-pagerduty` - * `-configs-api.notifications.disable-pushover` - * `-configs-api.notifications.disable-slack` - * `-configs-api.notifications.disable-opsgenie` - * `-configs-api.notifications.disable-webhook` - * `-configs-api.notifications.disable-victorops` - * `-configs-api.notifications.disable-wechat` + * `-configs.notifications.disable-email` + * `-configs.notifications.disable-webhook` * [FEATURE] Add /config HTTP endpoint which exposes the current Cortex configuration as YAML. #2165 * [FEATURE] Allow Prometheus remote write directly to ingesters. #1491 * [ENHANCEMENT] Add `status` label to `cortex_alertmanager_configs` metric to gauge the number of valid and invalid configs. #2125 diff --git a/docs/configuration/config-file-reference.md b/docs/configuration/config-file-reference.md index be729d2255f..f2b5731b2b4 100644 --- a/docs/configuration/config-file-reference.md +++ b/docs/configuration/config-file-reference.md @@ -108,13 +108,8 @@ Where default_value is the value to use if the environment variable is undefined # The ruler_config configures the Cortex ruler. [ruler: ] -# The configs_api_config configures the configs API used by the 'configs' -# service to expose APIs to manage them. -[configs_api: ] - -# The configdb_config configures the config database storing rules and alerts, -# and used by the 'configs' service to expose APIs to manage them. -[configdb: ] +# The configs_config configures the Cortex Configs API. +[configs: ] # The alertmanager_config configures the Cortex alertmanager. [alertmanager: ] @@ -2062,61 +2057,32 @@ The `fifo_cache_config` configures the local in-memory cache. [validity: | default = 0s] ``` -## `configs_api_config` +## `configs_config` -The `configs_api_config` configures the configs API used by the 'configs' service to expose APIs to manage them. +The `configs_config` configures the Cortex Configs API. ```yaml -notifications: - # Disable Email notifications for Alertmanager. - # CLI flag: -configs-api.notifications.disable-email - [allow_email: | default = false] - - # Disable PagerDuty notifications for Alertmanager. - # CLI flag: -configs-api.notifications.disable-pagerduty - [allow_pagerduty: | default = false] +database: + # URI where the database can be found (for dev you can use memory://) + # CLI flag: -configs.database.uri + [uri: | default = "postgres://postgres@configs-db.weave.local/configs?sslmode=disable"] - # Disable Pushover notifications for Alertmanager. - # CLI flag: -configs-api.notifications.disable-pushover - [allow_pushover: | default = false] + # Path where the database migration files can be found + # CLI flag: -configs.database.migrations + [migrations_dir: | default = ""] - # Disable Slack notifications for Alertmanager. - # CLI flag: -configs-api.notifications.disable-slack - [allow_slack: | default = false] + # File containing password (username goes in URI) + # CLI flag: -configs.database.password-file + [password_file: | default = ""] - # Disable OpsGenie notifications for Alertmanager. - # CLI flag: -configs-api.notifications.disable-opsgenie - [allow_opsgenie: | default = false] +notifications: + # Disable Email notifications for Alertmanager. + # CLI flag: -configs.notifications.disable-email + [disable_email: | default = false] # Disable WebHook notifications for Alertmanager. - # CLI flag: -configs-api.notifications.disable-webhook - [allow_webhook: | default = false] - - # Disable VictorOps notifications for Alertmanager. - # CLI flag: -configs-api.notifications.disable-victorops - [allow_victorops: | default = false] - - # Disable WeChat notifications for Alertmanager. - # CLI flag: -configs-api.notifications.disable-wechat - [allow_wechat: | default = false] -``` - -## `configdb_config` - -The `configdb_config` configures the config database storing rules and alerts, and used by the 'configs' service to expose APIs to manage them. - -```yaml -# URI where the database can be found (for dev you can use memory://) -# CLI flag: -database.uri -[uri: | default = "postgres://postgres@configs-db.weave.local/configs?sslmode=disable"] - -# Path where the database migration files can be found -# CLI flag: -database.migrations -[migrationsdir: | default = ""] - -# File containing password (username goes in URI) -# CLI flag: -database.password-file -[passwordfile: | default = ""] + # CLI flag: -configs.notifications.disable-webhook + [disable_webhook: | default = false] ``` ## `configstore_config` diff --git a/pkg/configs/api/api.go b/pkg/configs/api/api.go index 1dc34c56e90..bf6453b1744 100644 --- a/pkg/configs/api/api.go +++ b/pkg/configs/api/api.go @@ -20,34 +20,23 @@ import ( "github.com/cortexproject/cortex/pkg/util" ) -// Config configures the configs API. +// Config configures Configs API type Config struct { + DB db.Config `yaml:"database"` Notifications NotificationsConfig `yaml:"notifications"` } // NotificationsConfig configures Alertmanager notifications method. type NotificationsConfig struct { - DisableEmail bool `yaml:"allow_email"` - DisablePagerDuty bool `yaml:"allow_pagerduty"` - DisablePushover bool `yaml:"allow_pushover"` - DisableSlack bool `yaml:"allow_slack"` - DisableOpsGenie bool `yaml:"allow_opsgenie"` - DisableWebHook bool `yaml:"allow_webhook"` - DisableVictorOps bool `yaml:"allow_victorops"` - DisableWeChat bool `yaml:"allow_wechat"` - // Hipchat has reached end of life and is no longer available + DisableEmail bool `yaml:"disable_email"` + DisableWebHook bool `yaml:"disable_webhook"` } -// RegisterFlagsWithPrefix adds the flags required to config this to the given FlagSet +// RegisterFlags adds the flags required to configure this to the given FlagSet. func (cfg *Config) RegisterFlags(f *flag.FlagSet) { - f.BoolVar(&cfg.Notifications.DisableEmail, "configs-api.notifications.disable-email", false, "Disable Email notifications for Alertmanager.") - f.BoolVar(&cfg.Notifications.DisablePagerDuty, "configs-api.notifications.disable-pagerduty", false, "Disable PagerDuty notifications for Alertmanager.") - f.BoolVar(&cfg.Notifications.DisablePushover, "configs-api.notifications.disable-pushover", false, "Disable Pushover notifications for Alertmanager.") - f.BoolVar(&cfg.Notifications.DisableSlack, "configs-api.notifications.disable-slack", false, "Disable Slack notifications for Alertmanager.") - f.BoolVar(&cfg.Notifications.DisableOpsGenie, "configs-api.notifications.disable-opsgenie", false, "Disable OpsGenie notifications for Alertmanager.") - f.BoolVar(&cfg.Notifications.DisableWebHook, "configs-api.notifications.disable-webhook", false, "Disable WebHook notifications for Alertmanager.") - f.BoolVar(&cfg.Notifications.DisableVictorOps, "configs-api.notifications.disable-victorops", false, "Disable VictorOps notifications for Alertmanager.") - f.BoolVar(&cfg.Notifications.DisableWeChat, "configs-api.notifications.disable-wechat", false, "Disable WeChat notifications for Alertmanager.") + f.BoolVar(&cfg.Notifications.DisableEmail, "configs.notifications.disable-email", false, "Disable Email notifications for Alertmanager.") + f.BoolVar(&cfg.Notifications.DisableWebHook, "configs.notifications.disable-webhook", false, "Disable WebHook notifications for Alertmanager.") + cfg.DB.RegisterFlags(f) } // API implements the configs api. @@ -209,27 +198,9 @@ func validateAlertmanagerConfig(cfg string, noCfg NotificationsConfig) error { if noCfg.DisableEmail && len(recv.EmailConfigs) > 0 { return fmt.Errorf("email notifications are disabled in Cortex yet") } - if noCfg.DisablePagerDuty && len(recv.PagerdutyConfigs) > 0 { - return fmt.Errorf("pager-duty notifications are disabled in Cortex yet") - } - if noCfg.DisablePushover && len(recv.PushoverConfigs) > 0 { - return fmt.Errorf("pushover notifications are disabled in Cortex yet") - } - if noCfg.DisableSlack && len(recv.SlackConfigs) > 0 { - return fmt.Errorf("slack notifications are disabled in Cortex yet") - } - if noCfg.DisableOpsGenie && len(recv.OpsGenieConfigs) > 0 { - return fmt.Errorf("ops-genie notifications are disabled in Cortex yet") - } if noCfg.DisableWebHook && len(recv.WebhookConfigs) > 0 { return fmt.Errorf("web-hook notifications are disabled in Cortex yet") } - if noCfg.DisableVictorOps && len(recv.VictorOpsConfigs) > 0 { - return fmt.Errorf("victor-ops notifications are disabled in Cortex yet") - } - if noCfg.DisableWeChat && len(recv.WechatConfigs) > 0 { - return fmt.Errorf("we-chat notifications are disabled in Cortex yet") - } } return nil diff --git a/pkg/configs/db/db.go b/pkg/configs/db/db.go index fd2f2b9dc37..f2e215fe2ed 100644 --- a/pkg/configs/db/db.go +++ b/pkg/configs/db/db.go @@ -14,9 +14,9 @@ import ( // Config configures the database. type Config struct { - URI string - MigrationsDir string - PasswordFile string + URI string `yaml:"uri"` + MigrationsDir string `yaml:"migrations_dir"` + PasswordFile string `yaml:"password_file"` // Allow injection of mock DBs for unit testing. Mock DB `yaml:"-"` @@ -24,9 +24,9 @@ type Config struct { // RegisterFlags adds the flags required to configure this to the given FlagSet. func (cfg *Config) RegisterFlags(f *flag.FlagSet) { - f.StringVar(&cfg.URI, "database.uri", "postgres://postgres@configs-db.weave.local/configs?sslmode=disable", "URI where the database can be found (for dev you can use memory://)") - f.StringVar(&cfg.MigrationsDir, "database.migrations", "", "Path where the database migration files can be found") - f.StringVar(&cfg.PasswordFile, "database.password-file", "", "File containing password (username goes in URI)") + f.StringVar(&cfg.URI, "configs.database.uri", "postgres://postgres@configs-db.weave.local/configs?sslmode=disable", "URI where the database can be found (for dev you can use memory://)") + f.StringVar(&cfg.MigrationsDir, "configs.database.migrations", "", "Path where the database migration files can be found") + f.StringVar(&cfg.PasswordFile, "configs.database.password-file", "", "File containing password (username goes in URI)") } // DB is the interface for the database. diff --git a/pkg/cortex/cortex.go b/pkg/cortex/cortex.go index 1438d2fc482..d4e89e8538c 100644 --- a/pkg/cortex/cortex.go +++ b/pkg/cortex/cortex.go @@ -81,8 +81,7 @@ type Config struct { Compactor compactor.Config `yaml:"compactor,omitempty" doc:"hidden"` Ruler ruler.Config `yaml:"ruler,omitempty"` - ConfigsAPI api.Config `yaml:"configs_api,omitempty"` - ConfigDB db.Config `yaml:"configdb,omitempty"` + Configs api.Config `yaml:"configs,omitempty"` Alertmanager alertmanager.MultitenantAlertmanagerConfig `yaml:"alertmanager,omitempty"` RuntimeConfig runtimeconfig.ManagerConfig `yaml:"runtime_config,omitempty"` MemberlistKV memberlist.KVConfig `yaml:"memberlist"` @@ -117,8 +116,7 @@ func (c *Config) RegisterFlags(f *flag.FlagSet) { c.Compactor.RegisterFlags(f) c.Ruler.RegisterFlags(f) - c.ConfigsAPI.RegisterFlags(f) - c.ConfigDB.RegisterFlags(f) + c.Configs.RegisterFlags(f) c.Alertmanager.RegisterFlags(f) c.RuntimeConfig.RegisterFlags(f) c.MemberlistKV.RegisterFlags(f, "") diff --git a/pkg/cortex/modules.go b/pkg/cortex/modules.go index b58e16db30b..724e829415b 100644 --- a/pkg/cortex/modules.go +++ b/pkg/cortex/modules.go @@ -517,12 +517,12 @@ func (t *Cortex) stopRuler() error { } func (t *Cortex) initConfigs(cfg *Config) (err error) { - t.configDB, err = db.New(cfg.ConfigDB) + t.configDB, err = db.New(cfg.Configs.DB) if err != nil { return } - t.configAPI = api.New(t.configDB, cfg.ConfigsAPI) + t.configAPI = api.New(t.configDB, cfg.Configs) t.configAPI.RegisterRoutes(t.server.HTTP) return } diff --git a/tools/doc-generator/main.go b/tools/doc-generator/main.go index c49bb3dbabc..fe83655b0a5 100644 --- a/tools/doc-generator/main.go +++ b/tools/doc-generator/main.go @@ -6,16 +6,14 @@ import ( "reflect" "strings" - "github.com/cortexproject/cortex/pkg/configs/api" - "github.com/weaveworks/common/server" "github.com/cortexproject/cortex/pkg/alertmanager" "github.com/cortexproject/cortex/pkg/chunk" "github.com/cortexproject/cortex/pkg/chunk/cache" "github.com/cortexproject/cortex/pkg/chunk/storage" + "github.com/cortexproject/cortex/pkg/configs/api" config_client "github.com/cortexproject/cortex/pkg/configs/client" - "github.com/cortexproject/cortex/pkg/configs/db" "github.com/cortexproject/cortex/pkg/cortex" "github.com/cortexproject/cortex/pkg/distributor" "github.com/cortexproject/cortex/pkg/ingester" @@ -145,14 +143,9 @@ var ( desc: "The fifo_cache_config configures the local in-memory cache.", }, { - name: "configs_api_config", + name: "configs_config", structType: reflect.TypeOf(api.Config{}), - desc: "The configs_api_config configures the configs API used by the 'configs' service to expose APIs to manage them.", - }, - { - name: "configdb_config", - structType: reflect.TypeOf(db.Config{}), - desc: "The configdb_config configures the config database storing rules and alerts, and used by the 'configs' service to expose APIs to manage them.", + desc: "The configs_config configures the Cortex Configs API.", }, { name: "configstore_config", From 488de6ae523d6ef93c531ceea6503e8aba59936e Mon Sep 17 00:00:00 2001 From: Wing924 Date: Mon, 2 Mar 2020 11:42:34 +0900 Subject: [PATCH 05/12] wip Signed-off-by: Wing924 --- CHANGELOG.md | 9 +++++++-- pkg/configs/api/api.go | 4 ++-- tools/doc-generator/main.go | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a776bb5b674..bb2eac997bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,8 +25,13 @@ * [CHANGE] Updated Prometheus dependency to v2.16.0. This Prometheus version uses Active Query Tracker to limit concurrent queries. In order to keep `-querier.max-concurrent` working, Active Query Tracker is enabled by default, and is configured to store its data to `active-query-tracker` directory (relative to current directory when Cortex started). This can be changed by using `-querier.active-query-tracker-dir` option. Purpose of Active Query Tracker is to log queries that were running when Cortex crashes. This logging happens on next Cortex start. #2088 * [CHANGE] Experimental TSDB: TSDB head compaction interval and concurrency is now configurable (defaults to 1 min interval and 5 concurrent head compactions). New options: `-experimental.tsdb.head-compaction-interval` and `-experimental.tsdb.head-compaction-concurrency`. #2172 * [CHANGE] Remove fluentd-based billing infrastructure and flags such as `-distributor.enable-billing`. #1491 -* [CHNAGE] Renamed Configs API configuration options. - * `-database.*` -> `-configs.database.*` +* [CHNAGE] Renamed Configs configuration options. #2187 + * configuration options + * `-database.*` -> `-configs.database.*` + * config file + * `configdb:` -> `configs:` + * `configdb.migrationsdir:` -> `configs.migrations_dir:` + * `configdb.passwordfile:` -> `configs.password_file:` * [FEATURE] Added a read-only local alertmanager config store using files named corresponding to their tenant id. #2125 * [FEATURE] Added user sub rings to distribute users to a subset of ingesters. #1947 * `--experimental.distributor.user-subring-size` diff --git a/pkg/configs/api/api.go b/pkg/configs/api/api.go index bf6453b1744..64c39206404 100644 --- a/pkg/configs/api/api.go +++ b/pkg/configs/api/api.go @@ -196,10 +196,10 @@ func validateAlertmanagerConfig(cfg string, noCfg NotificationsConfig) error { for _, recv := range amCfg.Receivers { if noCfg.DisableEmail && len(recv.EmailConfigs) > 0 { - return fmt.Errorf("email notifications are disabled in Cortex yet") + return fmt.Errorf("email notifications are disabled") } if noCfg.DisableWebHook && len(recv.WebhookConfigs) > 0 { - return fmt.Errorf("web-hook notifications are disabled in Cortex yet") + return fmt.Errorf("webhook notifications are disabled") } } diff --git a/tools/doc-generator/main.go b/tools/doc-generator/main.go index fe83655b0a5..ee0b5aea661 100644 --- a/tools/doc-generator/main.go +++ b/tools/doc-generator/main.go @@ -145,7 +145,7 @@ var ( { name: "configs_config", structType: reflect.TypeOf(api.Config{}), - desc: "The configs_config configures the Cortex Configs API.", + desc: "The configs_config configures the Cortex Configs DB and API.", }, { name: "configstore_config", From f0e22523ed319920a8bb3ab6897c2e03db806760 Mon Sep 17 00:00:00 2001 From: Wing924 Date: Mon, 2 Mar 2020 12:45:50 +0900 Subject: [PATCH 06/12] fix Signed-off-by: Wing924 --- pkg/alertmanager/alerts/configdb/store.go | 5 ++- pkg/configs/api/api.go | 18 ++++---- pkg/configs/api/api_test.go | 23 +++++----- pkg/configs/api/helpers_test.go | 17 +++---- pkg/configs/client/client.go | 37 ++++++++-------- pkg/configs/client/configs_test.go | 12 ++--- pkg/configs/config.go | 19 ++++++++ pkg/configs/db/db.go | 18 ++++---- pkg/configs/db/memory/memory.go | 44 +++++++++---------- pkg/configs/db/postgres/postgres.go | 43 +++++++++--------- pkg/configs/db/timed.go | 30 ++++++------- pkg/configs/db/traced.go | 19 ++++---- .../{configs.go => userconfig/config.go} | 2 +- .../config_test.go} | 2 +- pkg/cortex/cortex.go | 4 +- pkg/cortex/modules.go | 2 +- pkg/ruler/rules/store.go | 7 +-- pkg/ruler/rules/store_test.go | 41 ++++++++--------- 18 files changed, 185 insertions(+), 158 deletions(-) create mode 100644 pkg/configs/config.go rename pkg/configs/{configs.go => userconfig/config.go} (99%) rename pkg/configs/{configs_test.go => userconfig/config_test.go} (99%) diff --git a/pkg/alertmanager/alerts/configdb/store.go b/pkg/alertmanager/alerts/configdb/store.go index 786ca29a461..92dd964d9af 100644 --- a/pkg/alertmanager/alerts/configdb/store.go +++ b/pkg/alertmanager/alerts/configdb/store.go @@ -3,15 +3,16 @@ package configdb import ( "context" + "github.com/cortexproject/cortex/pkg/configs/userconfig" + "github.com/cortexproject/cortex/pkg/alertmanager/alerts" - "github.com/cortexproject/cortex/pkg/configs" "github.com/cortexproject/cortex/pkg/configs/client" ) // Store is a concrete implementation of RuleStore that sources rules from the config service type Store struct { configClient client.Client - since configs.ID + since userconfig.ID alertConfigs map[string]alerts.AlertConfigDesc } diff --git a/pkg/configs/api/api.go b/pkg/configs/api/api.go index 64c39206404..81f5f91d863 100644 --- a/pkg/configs/api/api.go +++ b/pkg/configs/api/api.go @@ -15,14 +15,13 @@ import ( amconfig "github.com/prometheus/alertmanager/config" "github.com/weaveworks/common/user" - "github.com/cortexproject/cortex/pkg/configs" "github.com/cortexproject/cortex/pkg/configs/db" + "github.com/cortexproject/cortex/pkg/configs/userconfig" "github.com/cortexproject/cortex/pkg/util" ) // Config configures Configs API type Config struct { - DB db.Config `yaml:"database"` Notifications NotificationsConfig `yaml:"notifications"` } @@ -36,7 +35,6 @@ type NotificationsConfig struct { func (cfg *Config) RegisterFlags(f *flag.FlagSet) { f.BoolVar(&cfg.Notifications.DisableEmail, "configs.notifications.disable-email", false, "Disable Email notifications for Alertmanager.") f.BoolVar(&cfg.Notifications.DisableWebHook, "configs.notifications.disable-webhook", false, "Disable WebHook notifications for Alertmanager.") - cfg.DB.RegisterFlags(f) } // API implements the configs api. @@ -134,7 +132,7 @@ func (a *API) setConfig(w http.ResponseWriter, r *http.Request) { } logger := util.WithContext(r.Context(), util.Logger) - var cfg configs.Config + var cfg userconfig.Config if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil { // XXX: Untested level.Error(logger).Log("msg", "error decoding json body", "err", err) @@ -206,12 +204,12 @@ func validateAlertmanagerConfig(cfg string, noCfg NotificationsConfig) error { return nil } -func validateRulesFiles(c configs.Config) error { +func validateRulesFiles(c userconfig.Config) error { _, err := c.RulesConfig.Parse() return err } -func validateTemplateFiles(c configs.Config) error { +func validateTemplateFiles(c userconfig.Config) error { for fn, content := range c.TemplateFiles { if _, err := template.New(fn).Parse(content); err != nil { return err @@ -221,14 +219,14 @@ func validateTemplateFiles(c configs.Config) error { return nil } -// ConfigsView renders multiple configurations, mapping userID to configs.View. +// ConfigsView renders multiple configurations, mapping userID to userconfig.View. // Exposed only for tests. type ConfigsView struct { - Configs map[string]configs.View `json:"configs"` + Configs map[string]userconfig.View `json:"configs"` } func (a *API) getConfigs(w http.ResponseWriter, r *http.Request) { - var cfgs map[string]configs.View + var cfgs map[string]userconfig.View var cfgErr error logger := util.WithContext(r.Context(), util.Logger) rawSince := r.FormValue("since") @@ -241,7 +239,7 @@ func (a *API) getConfigs(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusBadRequest) return } - cfgs, cfgErr = a.db.GetConfigs(r.Context(), configs.ID(since)) + cfgs, cfgErr = a.db.GetConfigs(r.Context(), userconfig.ID(since)) } if cfgErr != nil { diff --git a/pkg/configs/api/api_test.go b/pkg/configs/api/api_test.go index 279d2604324..f0dd969fdaf 100644 --- a/pkg/configs/api/api_test.go +++ b/pkg/configs/api/api_test.go @@ -7,10 +7,11 @@ import ( "strings" "testing" + "github.com/cortexproject/cortex/pkg/configs/userconfig" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/cortexproject/cortex/pkg/configs" "github.com/cortexproject/cortex/pkg/configs/api" ) @@ -44,14 +45,14 @@ type configurable struct { } // post a config -func (c configurable) post(t *testing.T, userID string, config configs.Config) configs.View { +func (c configurable) post(t *testing.T, userID string, config userconfig.Config) userconfig.View { w := requestAsUser(t, userID, "POST", c.Endpoint, readerFromConfig(t, config)) require.Equal(t, http.StatusNoContent, w.Code) return c.get(t, userID) } // get a config -func (c configurable) get(t *testing.T, userID string) configs.View { +func (c configurable) get(t *testing.T, userID string) userconfig.View { w := requestAsUser(t, userID, "GET", c.Endpoint, nil) return parseView(t, w.Body.Bytes()) } @@ -153,11 +154,11 @@ func Test_GetAllConfigs_Empty(t *testing.T) { var found api.ConfigsView err := json.Unmarshal(w.Body.Bytes(), &found) assert.NoError(t, err, "Could not unmarshal JSON") - assert.Equal(t, api.ConfigsView{Configs: map[string]configs.View{}}, found) + assert.Equal(t, api.ConfigsView{Configs: map[string]userconfig.View{}}, found) } } -// GetAllConfigs returns all created configs. +// GetAllConfigs returns all created userconfig. func Test_GetAllConfigs(t *testing.T) { setup(t) defer cleanup(t) @@ -172,13 +173,13 @@ func Test_GetAllConfigs(t *testing.T) { var found api.ConfigsView err := json.Unmarshal(w.Body.Bytes(), &found) assert.NoError(t, err, "Could not unmarshal JSON") - assert.Equal(t, api.ConfigsView{Configs: map[string]configs.View{ + assert.Equal(t, api.ConfigsView{Configs: map[string]userconfig.View{ userID: view, }}, found) } } -// GetAllConfigs returns the *newest* versions of all created configs. +// GetAllConfigs returns the *newest* versions of all created userconfig. func Test_GetAllConfigs_Newest(t *testing.T) { setup(t) defer cleanup(t) @@ -195,7 +196,7 @@ func Test_GetAllConfigs_Newest(t *testing.T) { var found api.ConfigsView err := json.Unmarshal(w.Body.Bytes(), &found) assert.NoError(t, err, "Could not unmarshal JSON") - assert.Equal(t, api.ConfigsView{Configs: map[string]configs.View{ + assert.Equal(t, api.ConfigsView{Configs: map[string]userconfig.View{ userID: lastCreated, }}, found) } @@ -216,7 +217,7 @@ func Test_GetConfigs_IncludesNewerConfigsAndExcludesOlder(t *testing.T) { var found api.ConfigsView err := json.Unmarshal(w.Body.Bytes(), &found) assert.NoError(t, err, "Could not unmarshal JSON") - assert.Equal(t, api.ConfigsView{Configs: map[string]configs.View{ + assert.Equal(t, api.ConfigsView{Configs: map[string]userconfig.View{ userID3: config3, }}, found) } @@ -244,7 +245,7 @@ var amCfgValidationTests = []struct { email_configs: - to: myteam@foobar.org`, shouldFail: true, - errContains: "email notifications are disabled in Cortex yet", + errContains: "email notifications are disabled", }, { config: ` global: @@ -286,7 +287,7 @@ func Test_ValidateAlertmanagerConfig(t *testing.T) { func Test_SetConfig_ValidatesAlertmanagerConfig(t *testing.T) { userID := makeUserID() for i, test := range amCfgValidationTests { - cfg := configs.Config{AlertmanagerConfig: test.config} + cfg := userconfig.Config{AlertmanagerConfig: test.config} resp := requestAsUser(t, userID, "POST", "/api/prom/configs/alertmanager", readerFromConfig(t, cfg)) if !test.shouldFail { diff --git a/pkg/configs/api/helpers_test.go b/pkg/configs/api/helpers_test.go index b9cbe1e4230..3b4de0a10f7 100644 --- a/pkg/configs/api/helpers_test.go +++ b/pkg/configs/api/helpers_test.go @@ -9,10 +9,11 @@ import ( "net/http/httptest" "testing" + "github.com/cortexproject/cortex/pkg/configs/userconfig" + "github.com/stretchr/testify/require" "github.com/weaveworks/common/user" - "github.com/cortexproject/cortex/pkg/configs" "github.com/cortexproject/cortex/pkg/configs/api" "github.com/cortexproject/cortex/pkg/configs/db" "github.com/cortexproject/cortex/pkg/configs/db/dbtest" @@ -73,8 +74,8 @@ func makeUserID() string { } // makeConfig makes some arbitrary configuration. -func makeConfig() configs.Config { - return configs.Config{ +func makeConfig() userconfig.Config { + return userconfig.Config{ AlertmanagerConfig: makeString(` # Config no. %d. route: @@ -82,19 +83,19 @@ func makeConfig() configs.Config { receivers: - name: noop`), - RulesConfig: configs.RulesConfig{}, + RulesConfig: userconfig.RulesConfig{}, } } -func readerFromConfig(t *testing.T, config configs.Config) io.Reader { +func readerFromConfig(t *testing.T, config userconfig.Config) io.Reader { b, err := json.Marshal(config) require.NoError(t, err) return bytes.NewReader(b) } -// parseView parses a configs.View from JSON. -func parseView(t *testing.T, b []byte) configs.View { - var x configs.View +// parseView parses a userconfig.View from JSON. +func parseView(t *testing.T, b []byte) userconfig.View { + var x userconfig.View err := json.Unmarshal(b, &x) require.NoError(t, err, "Could not unmarshal JSON: %v", string(b)) return x diff --git a/pkg/configs/client/client.go b/pkg/configs/client/client.go index 5250d40ee6c..b8df442a471 100644 --- a/pkg/configs/client/client.go +++ b/pkg/configs/client/client.go @@ -9,17 +9,18 @@ import ( "net/url" "time" + "github.com/cortexproject/cortex/pkg/configs/userconfig" + "github.com/go-kit/kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/weaveworks/common/instrument" - "github.com/cortexproject/cortex/pkg/configs" "github.com/cortexproject/cortex/pkg/util" "github.com/cortexproject/cortex/pkg/util/flagext" ) -// Config says where we can find the ruler configs. +// Config says where we can find the ruler userconfig. type Config struct { ConfigsAPIURL flagext.URLValue ClientTimeout time.Duration // HTTP timeout duration for requests made to the Weave Cloud configs service. @@ -27,25 +28,25 @@ type Config struct { // RegisterFlagsWithPrefix adds the flags required to config this to the given FlagSet func (cfg *Config) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) { - f.Var(&cfg.ConfigsAPIURL, prefix+"configs.url", "URL of configs API server.") - f.DurationVar(&cfg.ClientTimeout, prefix+"configs.client-timeout", 5*time.Second, "Timeout for requests to Weave Cloud configs service.") + f.Var(&cfg.ConfigsAPIURL, prefix+"userconfig.url", "URL of configs API server.") + f.DurationVar(&cfg.ClientTimeout, prefix+"userconfig.client-timeout", 5*time.Second, "Timeout for requests to Weave Cloud configs service.") } var configsRequestDuration = instrument.NewHistogramCollector(promauto.NewHistogramVec(prometheus.HistogramOpts{ Namespace: "cortex", Name: "configs_request_duration_seconds", - Help: "Time spent requesting configs.", + Help: "Time spent requesting userconfig.", Buckets: prometheus.DefBuckets, }, []string{"operation", "status_code"})) // Client is what the ruler and altermanger needs from a config store to process rules. type Client interface { // GetRules returns all Cortex configurations from a configs API server - // that have been updated after the given configs.ID was last updated. - GetRules(ctx context.Context, since configs.ID) (map[string]configs.VersionedRulesConfig, error) + // that have been updated after the given userconfig.ID was last updated. + GetRules(ctx context.Context, since userconfig.ID) (map[string]userconfig.VersionedRulesConfig, error) // GetAlerts fetches all the alerts that have changes since since. - GetAlerts(ctx context.Context, since configs.ID) (*ConfigsResponse, error) + GetAlerts(ctx context.Context, since userconfig.ID) (*ConfigsResponse, error) } // New creates a new ConfigClient. @@ -63,7 +64,7 @@ type ConfigDBClient struct { } // GetRules implements Client -func (c ConfigDBClient) GetRules(ctx context.Context, since configs.ID) (map[string]configs.VersionedRulesConfig, error) { +func (c ConfigDBClient) GetRules(ctx context.Context, since userconfig.ID) (map[string]userconfig.VersionedRulesConfig, error) { suffix := "" if since != 0 { suffix = fmt.Sprintf("?since=%d", since) @@ -78,7 +79,7 @@ func (c ConfigDBClient) GetRules(ctx context.Context, since configs.ID) (map[str if err != nil { return nil, err } - configs := map[string]configs.VersionedRulesConfig{} + configs := map[string]userconfig.VersionedRulesConfig{} for id, view := range response.Configs { cfg := view.GetVersionedRulesConfig() if cfg != nil { @@ -89,7 +90,7 @@ func (c ConfigDBClient) GetRules(ctx context.Context, since configs.ID) (map[str } // GetAlerts implements Client. -func (c ConfigDBClient) GetAlerts(ctx context.Context, since configs.ID) (*ConfigsResponse, error) { +func (c ConfigDBClient) GetAlerts(ctx context.Context, since userconfig.ID) (*ConfigsResponse, error) { suffix := "" if since != 0 { suffix = fmt.Sprintf("?since=%d", since) @@ -104,7 +105,7 @@ func (c ConfigDBClient) GetAlerts(ctx context.Context, since configs.ID) (*Confi return response, err } -func doRequest(endpoint string, timeout time.Duration, since configs.ID) (*ConfigsResponse, error) { +func doRequest(endpoint string, timeout time.Duration, since userconfig.ID) (*ConfigsResponse, error) { req, err := http.NewRequest("GET", endpoint, nil) if err != nil { return nil, err @@ -132,17 +133,17 @@ func doRequest(endpoint string, timeout time.Duration, since configs.ID) (*Confi return &config, nil } -// ConfigsResponse is a response from server for GetConfigs. +// ConfigsResponse is a response from server for Getuserconfig. type ConfigsResponse struct { // The version since which these configs were changed - since configs.ID + since userconfig.ID - // Configs maps user ID to their latest configs.View. - Configs map[string]configs.View `json:"configs"` + // Configs maps user ID to their latest userconfig.View. + Configs map[string]userconfig.View `json:"configs"` } -// GetLatestConfigID returns the last config ID from a set of configs. -func (c ConfigsResponse) GetLatestConfigID() configs.ID { +// GetLatestConfigID returns the last config ID from a set of userconfig. +func (c ConfigsResponse) GetLatestConfigID() userconfig.ID { latest := c.since for _, config := range c.Configs { if config.ID > latest { diff --git a/pkg/configs/client/configs_test.go b/pkg/configs/client/configs_test.go index b4ed4b275b5..86b0427c7ee 100644 --- a/pkg/configs/client/configs_test.go +++ b/pkg/configs/client/configs_test.go @@ -6,11 +6,11 @@ import ( "testing" "time" + "github.com/cortexproject/cortex/pkg/configs/userconfig" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/assert" - - "github.com/cortexproject/cortex/pkg/configs" ) var response = `{ @@ -38,15 +38,15 @@ func TestDoRequest(t *testing.T) { resp, err := doRequest(server.URL, 1*time.Second, 0) assert.Nil(t, err) - expected := ConfigsResponse{Configs: map[string]configs.View{ + expected := ConfigsResponse{Configs: map[string]userconfig.View{ "2": { ID: 1, - Config: configs.Config{ - RulesConfig: configs.RulesConfig{ + Config: userconfig.Config{ + RulesConfig: userconfig.RulesConfig{ Files: map[string]string{ "recording.rules": "groups:\n- name: demo-service-alerts\n interval: 15s\n rules:\n - alert: SomethingIsUp\n expr: up == 1\n", }, - FormatVersion: configs.RuleFormatV2, + FormatVersion: userconfig.RuleFormatV2, }, }, }, diff --git a/pkg/configs/config.go b/pkg/configs/config.go new file mode 100644 index 00000000000..9ec1d68b648 --- /dev/null +++ b/pkg/configs/config.go @@ -0,0 +1,19 @@ +package configs + +import ( + "flag" + + "github.com/cortexproject/cortex/pkg/configs/api" + "github.com/cortexproject/cortex/pkg/configs/db" +) + +type Config struct { + DB db.Config `yaml:"database"` + API api.Config `yaml:"api"` +} + +// RegisterFlags adds the flags required to configure this to the given FlagSet. +func (cfg *Config) RegisterFlags(f *flag.FlagSet) { + cfg.DB.RegisterFlags(f) + cfg.API.RegisterFlags(f) +} diff --git a/pkg/configs/db/db.go b/pkg/configs/db/db.go index f2e215fe2ed..302ff4862b3 100644 --- a/pkg/configs/db/db.go +++ b/pkg/configs/db/db.go @@ -7,9 +7,9 @@ import ( "io/ioutil" "net/url" - "github.com/cortexproject/cortex/pkg/configs" "github.com/cortexproject/cortex/pkg/configs/db/memory" "github.com/cortexproject/cortex/pkg/configs/db/postgres" + "github.com/cortexproject/cortex/pkg/configs/userconfig" ) // Config configures the database. @@ -32,25 +32,25 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) { // DB is the interface for the database. type DB interface { // GetRulesConfig gets the user's ruler config - GetRulesConfig(ctx context.Context, userID string) (configs.VersionedRulesConfig, error) + GetRulesConfig(ctx context.Context, userID string) (userconfig.VersionedRulesConfig, error) // SetRulesConfig does a compare-and-swap (CAS) on the user's rules config. // `oldConfig` must precisely match the current config in order to change the config to `newConfig`. // Will return `true` if the config was updated, `false` otherwise. - SetRulesConfig(ctx context.Context, userID string, oldConfig, newConfig configs.RulesConfig) (bool, error) + SetRulesConfig(ctx context.Context, userID string, oldConfig, newConfig userconfig.RulesConfig) (bool, error) // GetAllRulesConfigs gets all of the ruler configs - GetAllRulesConfigs(ctx context.Context) (map[string]configs.VersionedRulesConfig, error) + GetAllRulesConfigs(ctx context.Context) (map[string]userconfig.VersionedRulesConfig, error) // GetRulesConfigs gets all of the configs that have been added or have // changed since the provided config. - GetRulesConfigs(ctx context.Context, since configs.ID) (map[string]configs.VersionedRulesConfig, error) + GetRulesConfigs(ctx context.Context, since userconfig.ID) (map[string]userconfig.VersionedRulesConfig, error) - GetConfig(ctx context.Context, userID string) (configs.View, error) - SetConfig(ctx context.Context, userID string, cfg configs.Config) error + GetConfig(ctx context.Context, userID string) (userconfig.View, error) + SetConfig(ctx context.Context, userID string, cfg userconfig.Config) error - GetAllConfigs(ctx context.Context) (map[string]configs.View, error) - GetConfigs(ctx context.Context, since configs.ID) (map[string]configs.View, error) + GetAllConfigs(ctx context.Context) (map[string]userconfig.View, error) + GetConfigs(ctx context.Context, since userconfig.ID) (map[string]userconfig.View, error) DeactivateConfig(ctx context.Context, userID string) error RestoreConfig(ctx context.Context, userID string) error diff --git a/pkg/configs/db/memory/memory.go b/pkg/configs/db/memory/memory.go index c2f8bbe2c0c..a759c425bd0 100644 --- a/pkg/configs/db/memory/memory.go +++ b/pkg/configs/db/memory/memory.go @@ -6,50 +6,50 @@ import ( "fmt" "time" - "github.com/cortexproject/cortex/pkg/configs" + "github.com/cortexproject/cortex/pkg/configs/userconfig" ) // DB is an in-memory database for testing, and local development type DB struct { - cfgs map[string]configs.View + cfgs map[string]userconfig.View id uint } // New creates a new in-memory database func New(_, _ string) (*DB, error) { return &DB{ - cfgs: map[string]configs.View{}, + cfgs: map[string]userconfig.View{}, id: 0, }, nil } // GetConfig gets the user's configuration. -func (d *DB) GetConfig(ctx context.Context, userID string) (configs.View, error) { +func (d *DB) GetConfig(ctx context.Context, userID string) (userconfig.View, error) { c, ok := d.cfgs[userID] if !ok { - return configs.View{}, sql.ErrNoRows + return userconfig.View{}, sql.ErrNoRows } return c, nil } // SetConfig sets configuration for a user. -func (d *DB) SetConfig(ctx context.Context, userID string, cfg configs.Config) error { +func (d *DB) SetConfig(ctx context.Context, userID string, cfg userconfig.Config) error { if !cfg.RulesConfig.FormatVersion.IsValid() { return fmt.Errorf("invalid rule format version %v", cfg.RulesConfig.FormatVersion) } - d.cfgs[userID] = configs.View{Config: cfg, ID: configs.ID(d.id)} + d.cfgs[userID] = userconfig.View{Config: cfg, ID: userconfig.ID(d.id)} d.id++ return nil } -// GetAllConfigs gets all of the configs. -func (d *DB) GetAllConfigs(ctx context.Context) (map[string]configs.View, error) { +// GetAllConfigs gets all of the userconfig. +func (d *DB) GetAllConfigs(ctx context.Context) (map[string]userconfig.View, error) { return d.cfgs, nil } // GetConfigs gets all of the configs that have changed recently. -func (d *DB) GetConfigs(ctx context.Context, since configs.ID) (map[string]configs.View, error) { - cfgs := map[string]configs.View{} +func (d *DB) GetConfigs(ctx context.Context, since userconfig.ID) (map[string]userconfig.View, error) { + cfgs := map[string]userconfig.View{} for user, c := range d.cfgs { if c.ID > since { cfgs[user] = c @@ -67,7 +67,7 @@ func (d *DB) SetDeletedAtConfig(ctx context.Context, userID string, deletedAt ti return err } cv.DeletedAt = deletedAt - cv.ID = configs.ID(d.id) + cv.ID = userconfig.ID(d.id) d.cfgs[userID] = cv d.id++ return nil @@ -89,36 +89,36 @@ func (d *DB) Close() error { } // GetRulesConfig gets the rules config for a user. -func (d *DB) GetRulesConfig(ctx context.Context, userID string) (configs.VersionedRulesConfig, error) { +func (d *DB) GetRulesConfig(ctx context.Context, userID string) (userconfig.VersionedRulesConfig, error) { c, ok := d.cfgs[userID] if !ok { - return configs.VersionedRulesConfig{}, sql.ErrNoRows + return userconfig.VersionedRulesConfig{}, sql.ErrNoRows } cfg := c.GetVersionedRulesConfig() if cfg == nil { - return configs.VersionedRulesConfig{}, sql.ErrNoRows + return userconfig.VersionedRulesConfig{}, sql.ErrNoRows } return *cfg, nil } // SetRulesConfig sets the rules config for a user. -func (d *DB) SetRulesConfig(ctx context.Context, userID string, oldConfig, newConfig configs.RulesConfig) (bool, error) { +func (d *DB) SetRulesConfig(ctx context.Context, userID string, oldConfig, newConfig userconfig.RulesConfig) (bool, error) { c, ok := d.cfgs[userID] if !ok { - return true, d.SetConfig(ctx, userID, configs.Config{RulesConfig: newConfig}) + return true, d.SetConfig(ctx, userID, userconfig.Config{RulesConfig: newConfig}) } if !oldConfig.Equal(c.Config.RulesConfig) { return false, nil } - return true, d.SetConfig(ctx, userID, configs.Config{ + return true, d.SetConfig(ctx, userID, userconfig.Config{ AlertmanagerConfig: c.Config.AlertmanagerConfig, RulesConfig: newConfig, }) } // GetAllRulesConfigs gets the rules configs for all users that have them. -func (d *DB) GetAllRulesConfigs(ctx context.Context) (map[string]configs.VersionedRulesConfig, error) { - cfgs := map[string]configs.VersionedRulesConfig{} +func (d *DB) GetAllRulesConfigs(ctx context.Context) (map[string]userconfig.VersionedRulesConfig, error) { + cfgs := map[string]userconfig.VersionedRulesConfig{} for user, c := range d.cfgs { cfg := c.GetVersionedRulesConfig() if cfg != nil { @@ -130,8 +130,8 @@ func (d *DB) GetAllRulesConfigs(ctx context.Context) (map[string]configs.Version // GetRulesConfigs gets the rules configs that have changed // since the given config version. -func (d *DB) GetRulesConfigs(ctx context.Context, since configs.ID) (map[string]configs.VersionedRulesConfig, error) { - cfgs := map[string]configs.VersionedRulesConfig{} +func (d *DB) GetRulesConfigs(ctx context.Context, since userconfig.ID) (map[string]userconfig.VersionedRulesConfig, error) { + cfgs := map[string]userconfig.VersionedRulesConfig{} for user, c := range d.cfgs { if c.ID <= since { continue diff --git a/pkg/configs/db/postgres/postgres.go b/pkg/configs/db/postgres/postgres.go index 9247addd1b9..6476891f625 100644 --- a/pkg/configs/db/postgres/postgres.go +++ b/pkg/configs/db/postgres/postgres.go @@ -8,6 +8,8 @@ import ( "strings" "time" + "github.com/cortexproject/cortex/pkg/configs/userconfig" + "github.com/Masterminds/squirrel" "github.com/go-kit/kit/log/level" "github.com/golang-migrate/migrate/v4" @@ -17,7 +19,6 @@ import ( _ "github.com/lib/pq" // Import the postgres sql driver "github.com/pkg/errors" - "github.com/cortexproject/cortex/pkg/configs" "github.com/cortexproject/cortex/pkg/util" ) @@ -105,7 +106,7 @@ func New(uri, migrationsDir string) (DB, error) { var statementBuilder = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).RunWith -func (d DB) findConfigs(filter squirrel.Sqlizer) (map[string]configs.View, error) { +func (d DB) findConfigs(filter squirrel.Sqlizer) (map[string]userconfig.View, error) { rows, err := d.Select("id", "owner_id", "config", "deleted_at"). Options("DISTINCT ON (owner_id)"). From("configs"). @@ -116,9 +117,9 @@ func (d DB) findConfigs(filter squirrel.Sqlizer) (map[string]configs.View, error return nil, err } defer rows.Close() - cfgs := map[string]configs.View{} + cfgs := map[string]userconfig.View{} for rows.Next() { - var cfg configs.View + var cfg userconfig.View var cfgBytes []byte var userID string var deletedAt pq.NullTime @@ -137,8 +138,8 @@ func (d DB) findConfigs(filter squirrel.Sqlizer) (map[string]configs.View, error } // GetConfig gets a configuration. -func (d DB) GetConfig(ctx context.Context, userID string) (configs.View, error) { - var cfgView configs.View +func (d DB) GetConfig(ctx context.Context, userID string) (userconfig.View, error) { + var cfgView userconfig.View var cfgBytes []byte var deletedAt pq.NullTime err := d.Select("id", "config", "deleted_at"). @@ -156,7 +157,7 @@ func (d DB) GetConfig(ctx context.Context, userID string) (configs.View, error) } // SetConfig sets a configuration. -func (d DB) SetConfig(ctx context.Context, userID string, cfg configs.Config) error { +func (d DB) SetConfig(ctx context.Context, userID string, cfg userconfig.Config) error { if !cfg.RulesConfig.FormatVersion.IsValid() { return fmt.Errorf("invalid rule format version %v", cfg.RulesConfig.FormatVersion) } @@ -172,13 +173,13 @@ func (d DB) SetConfig(ctx context.Context, userID string, cfg configs.Config) er return err } -// GetAllConfigs gets all of the configs. -func (d DB) GetAllConfigs(ctx context.Context) (map[string]configs.View, error) { +// GetAllConfigs gets all of the userconfig. +func (d DB) GetAllConfigs(ctx context.Context) (map[string]userconfig.View, error) { return d.findConfigs(allConfigs) } // GetConfigs gets all of the configs that have changed recently. -func (d DB) GetConfigs(ctx context.Context, since configs.ID) (map[string]configs.View, error) { +func (d DB) GetConfigs(ctx context.Context, since userconfig.ID) (map[string]userconfig.View, error) { return d.findConfigs(squirrel.And{ allConfigs, squirrel.Gt{"id": since}, @@ -186,20 +187,20 @@ func (d DB) GetConfigs(ctx context.Context, since configs.ID) (map[string]config } // GetRulesConfig gets the latest alertmanager config for a user. -func (d DB) GetRulesConfig(ctx context.Context, userID string) (configs.VersionedRulesConfig, error) { +func (d DB) GetRulesConfig(ctx context.Context, userID string) (userconfig.VersionedRulesConfig, error) { current, err := d.GetConfig(ctx, userID) if err != nil { - return configs.VersionedRulesConfig{}, err + return userconfig.VersionedRulesConfig{}, err } cfg := current.GetVersionedRulesConfig() if cfg == nil { - return configs.VersionedRulesConfig{}, sql.ErrNoRows + return userconfig.VersionedRulesConfig{}, sql.ErrNoRows } return *cfg, nil } // SetRulesConfig sets the current alertmanager config for a user. -func (d DB) SetRulesConfig(ctx context.Context, userID string, oldConfig, newConfig configs.RulesConfig) (bool, error) { +func (d DB) SetRulesConfig(ctx context.Context, userID string, oldConfig, newConfig userconfig.RulesConfig) (bool, error) { updated := false err := d.Transaction(func(tx DB) error { current, err := d.GetConfig(ctx, userID) @@ -212,7 +213,7 @@ func (d DB) SetRulesConfig(ctx context.Context, userID string, oldConfig, newCon if !((err == sql.ErrNoRows && oldConfig.Files == nil) || oldConfig.Equal(current.Config.RulesConfig)) { return nil } - new := configs.Config{ + new := userconfig.Config{ AlertmanagerConfig: current.Config.AlertmanagerConfig, RulesConfig: newConfig, } @@ -224,7 +225,7 @@ func (d DB) SetRulesConfig(ctx context.Context, userID string, oldConfig, newCon // findRulesConfigs helps GetAllRulesConfigs and GetRulesConfigs retrieve the // set of all active rules configurations across all our users. -func (d DB) findRulesConfigs(filter squirrel.Sqlizer) (map[string]configs.VersionedRulesConfig, error) { +func (d DB) findRulesConfigs(filter squirrel.Sqlizer) (map[string]userconfig.VersionedRulesConfig, error) { rows, err := d.Select("id", "owner_id", "config ->> 'rules_files'", "config ->> 'rule_format_version'", "deleted_at"). Options("DISTINCT ON (owner_id)"). From("configs"). @@ -245,9 +246,9 @@ func (d DB) findRulesConfigs(filter squirrel.Sqlizer) (map[string]configs.Versio return nil, err } defer rows.Close() - cfgs := map[string]configs.VersionedRulesConfig{} + cfgs := map[string]userconfig.VersionedRulesConfig{} for rows.Next() { - var cfg configs.VersionedRulesConfig + var cfg userconfig.VersionedRulesConfig var userID string var cfgBytes []byte var rfvBytes []byte @@ -275,12 +276,12 @@ func (d DB) findRulesConfigs(filter squirrel.Sqlizer) (map[string]configs.Versio } // GetAllRulesConfigs gets all alertmanager configs for all users. -func (d DB) GetAllRulesConfigs(ctx context.Context) (map[string]configs.VersionedRulesConfig, error) { +func (d DB) GetAllRulesConfigs(ctx context.Context) (map[string]userconfig.VersionedRulesConfig, error) { return d.findRulesConfigs(allConfigs) } // GetRulesConfigs gets all the alertmanager configs that have changed since a given config. -func (d DB) GetRulesConfigs(ctx context.Context, since configs.ID) (map[string]configs.VersionedRulesConfig, error) { +func (d DB) GetRulesConfigs(ctx context.Context, since userconfig.ID) (map[string]userconfig.VersionedRulesConfig, error) { return d.findRulesConfigs(squirrel.And{ allConfigs, squirrel.Gt{"id": since}, @@ -290,7 +291,7 @@ func (d DB) GetRulesConfigs(ctx context.Context, since configs.ID) (map[string]c // SetDeletedAtConfig sets a deletedAt for configuration // by adding a single new row with deleted_at set // the same as SetConfig is actually insert -func (d DB) SetDeletedAtConfig(ctx context.Context, userID string, deletedAt pq.NullTime, cfg configs.Config) error { +func (d DB) SetDeletedAtConfig(ctx context.Context, userID string, deletedAt pq.NullTime, cfg userconfig.Config) error { cfgBytes, err := json.Marshal(cfg) if err != nil { return err diff --git a/pkg/configs/db/timed.go b/pkg/configs/db/timed.go index f7bbd6d6cd4..58cbfdc9e19 100644 --- a/pkg/configs/db/timed.go +++ b/pkg/configs/db/timed.go @@ -6,7 +6,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/weaveworks/common/instrument" - "github.com/cortexproject/cortex/pkg/configs" + "github.com/cortexproject/cortex/pkg/configs/userconfig" ) var ( @@ -27,8 +27,8 @@ type timed struct { d DB } -func (t timed) GetConfig(ctx context.Context, userID string) (configs.View, error) { - var cfg configs.View +func (t timed) GetConfig(ctx context.Context, userID string) (userconfig.View, error) { + var cfg userconfig.View err := instrument.CollectedRequest(ctx, "DB.GetConfigs", databaseRequestDuration, instrument.ErrorCode, func(ctx context.Context) error { var err error cfg, err = t.d.GetConfig(ctx, userID) // Warning: this will produce an incorrect result if the configID ever overflows @@ -37,14 +37,14 @@ func (t timed) GetConfig(ctx context.Context, userID string) (configs.View, erro return cfg, err } -func (t timed) SetConfig(ctx context.Context, userID string, cfg configs.Config) error { +func (t timed) SetConfig(ctx context.Context, userID string, cfg userconfig.Config) error { return instrument.CollectedRequest(ctx, "DB.SetConfig", databaseRequestDuration, instrument.ErrorCode, func(ctx context.Context) error { return t.d.SetConfig(ctx, userID, cfg) // Warning: this will produce an incorrect result if the configID ever overflows }) } -func (t timed) GetAllConfigs(ctx context.Context) (map[string]configs.View, error) { - var cfgs map[string]configs.View +func (t timed) GetAllConfigs(ctx context.Context) (map[string]userconfig.View, error) { + var cfgs map[string]userconfig.View err := instrument.CollectedRequest(ctx, "DB.GetAllConfigs", databaseRequestDuration, instrument.ErrorCode, func(ctx context.Context) error { var err error cfgs, err = t.d.GetAllConfigs(ctx) @@ -54,8 +54,8 @@ func (t timed) GetAllConfigs(ctx context.Context) (map[string]configs.View, erro return cfgs, err } -func (t timed) GetConfigs(ctx context.Context, since configs.ID) (map[string]configs.View, error) { - var cfgs map[string]configs.View +func (t timed) GetConfigs(ctx context.Context, since userconfig.ID) (map[string]userconfig.View, error) { + var cfgs map[string]userconfig.View err := instrument.CollectedRequest(ctx, "DB.GetConfigs", databaseRequestDuration, instrument.ErrorCode, func(ctx context.Context) error { var err error cfgs, err = t.d.GetConfigs(ctx, since) @@ -83,8 +83,8 @@ func (t timed) Close() error { }) } -func (t timed) GetRulesConfig(ctx context.Context, userID string) (configs.VersionedRulesConfig, error) { - var cfg configs.VersionedRulesConfig +func (t timed) GetRulesConfig(ctx context.Context, userID string) (userconfig.VersionedRulesConfig, error) { + var cfg userconfig.VersionedRulesConfig err := instrument.CollectedRequest(ctx, "DB.GetRulesConfig", databaseRequestDuration, instrument.ErrorCode, func(ctx context.Context) error { var err error cfg, err = t.d.GetRulesConfig(ctx, userID) @@ -94,7 +94,7 @@ func (t timed) GetRulesConfig(ctx context.Context, userID string) (configs.Versi return cfg, err } -func (t timed) SetRulesConfig(ctx context.Context, userID string, oldCfg, newCfg configs.RulesConfig) (bool, error) { +func (t timed) SetRulesConfig(ctx context.Context, userID string, oldCfg, newCfg userconfig.RulesConfig) (bool, error) { var updated bool err := instrument.CollectedRequest(ctx, "DB.SetRulesConfig", databaseRequestDuration, instrument.ErrorCode, func(ctx context.Context) error { var err error @@ -105,8 +105,8 @@ func (t timed) SetRulesConfig(ctx context.Context, userID string, oldCfg, newCfg return updated, err } -func (t timed) GetAllRulesConfigs(ctx context.Context) (map[string]configs.VersionedRulesConfig, error) { - var cfgs map[string]configs.VersionedRulesConfig +func (t timed) GetAllRulesConfigs(ctx context.Context) (map[string]userconfig.VersionedRulesConfig, error) { + var cfgs map[string]userconfig.VersionedRulesConfig err := instrument.CollectedRequest(ctx, "DB.GetAllRulesConfigs", databaseRequestDuration, instrument.ErrorCode, func(ctx context.Context) error { var err error cfgs, err = t.d.GetAllRulesConfigs(ctx) @@ -116,8 +116,8 @@ func (t timed) GetAllRulesConfigs(ctx context.Context) (map[string]configs.Versi return cfgs, err } -func (t timed) GetRulesConfigs(ctx context.Context, since configs.ID) (map[string]configs.VersionedRulesConfig, error) { - var cfgs map[string]configs.VersionedRulesConfig +func (t timed) GetRulesConfigs(ctx context.Context, since userconfig.ID) (map[string]userconfig.VersionedRulesConfig, error) { + var cfgs map[string]userconfig.VersionedRulesConfig err := instrument.CollectedRequest(ctx, "DB.GetRulesConfigs", databaseRequestDuration, instrument.ErrorCode, func(ctx context.Context) error { var err error cfgs, err = t.d.GetRulesConfigs(ctx, since) diff --git a/pkg/configs/db/traced.go b/pkg/configs/db/traced.go index 2549b86be0d..7a2cc3aac61 100644 --- a/pkg/configs/db/traced.go +++ b/pkg/configs/db/traced.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/cortexproject/cortex/pkg/configs/userconfig" + "github.com/go-kit/kit/log/level" - "github.com/cortexproject/cortex/pkg/configs" "github.com/cortexproject/cortex/pkg/util" ) @@ -19,22 +20,22 @@ func (t traced) trace(name string, args ...interface{}) { level.Debug(util.Logger).Log("msg", fmt.Sprintf("%s: %#v", name, args)) } -func (t traced) GetConfig(ctx context.Context, userID string) (cfg configs.View, err error) { +func (t traced) GetConfig(ctx context.Context, userID string) (cfg userconfig.View, err error) { defer func() { t.trace("GetConfig", userID, cfg, err) }() return t.d.GetConfig(ctx, userID) } -func (t traced) SetConfig(ctx context.Context, userID string, cfg configs.Config) (err error) { +func (t traced) SetConfig(ctx context.Context, userID string, cfg userconfig.Config) (err error) { defer func() { t.trace("SetConfig", userID, cfg, err) }() return t.d.SetConfig(ctx, userID, cfg) } -func (t traced) GetAllConfigs(ctx context.Context) (cfgs map[string]configs.View, err error) { +func (t traced) GetAllConfigs(ctx context.Context) (cfgs map[string]userconfig.View, err error) { defer func() { t.trace("GetAllConfigs", cfgs, err) }() return t.d.GetAllConfigs(ctx) } -func (t traced) GetConfigs(ctx context.Context, since configs.ID) (cfgs map[string]configs.View, err error) { +func (t traced) GetConfigs(ctx context.Context, since userconfig.ID) (cfgs map[string]userconfig.View, err error) { defer func() { t.trace("GetConfigs", since, cfgs, err) }() return t.d.GetConfigs(ctx, since) } @@ -54,22 +55,22 @@ func (t traced) Close() (err error) { return t.d.Close() } -func (t traced) GetRulesConfig(ctx context.Context, userID string) (cfg configs.VersionedRulesConfig, err error) { +func (t traced) GetRulesConfig(ctx context.Context, userID string) (cfg userconfig.VersionedRulesConfig, err error) { defer func() { t.trace("GetRulesConfig", userID, cfg, err) }() return t.d.GetRulesConfig(ctx, userID) } -func (t traced) SetRulesConfig(ctx context.Context, userID string, oldCfg, newCfg configs.RulesConfig) (updated bool, err error) { +func (t traced) SetRulesConfig(ctx context.Context, userID string, oldCfg, newCfg userconfig.RulesConfig) (updated bool, err error) { defer func() { t.trace("SetRulesConfig", userID, oldCfg, newCfg, updated, err) }() return t.d.SetRulesConfig(ctx, userID, oldCfg, newCfg) } -func (t traced) GetAllRulesConfigs(ctx context.Context) (cfgs map[string]configs.VersionedRulesConfig, err error) { +func (t traced) GetAllRulesConfigs(ctx context.Context) (cfgs map[string]userconfig.VersionedRulesConfig, err error) { defer func() { t.trace("GetAllRulesConfigs", cfgs, err) }() return t.d.GetAllRulesConfigs(ctx) } -func (t traced) GetRulesConfigs(ctx context.Context, since configs.ID) (cfgs map[string]configs.VersionedRulesConfig, err error) { +func (t traced) GetRulesConfigs(ctx context.Context, since userconfig.ID) (cfgs map[string]userconfig.VersionedRulesConfig, err error) { defer func() { t.trace("GetConfigs", since, cfgs, err) }() return t.d.GetRulesConfigs(ctx, since) } diff --git a/pkg/configs/configs.go b/pkg/configs/userconfig/config.go similarity index 99% rename from pkg/configs/configs.go rename to pkg/configs/userconfig/config.go index 00554b07a9b..7d34c498db8 100644 --- a/pkg/configs/configs.go +++ b/pkg/configs/userconfig/config.go @@ -1,4 +1,4 @@ -package configs +package userconfig import ( "encoding/json" diff --git a/pkg/configs/configs_test.go b/pkg/configs/userconfig/config_test.go similarity index 99% rename from pkg/configs/configs_test.go rename to pkg/configs/userconfig/config_test.go index 32c19bb90a6..ecf565ebc46 100644 --- a/pkg/configs/configs_test.go +++ b/pkg/configs/userconfig/config_test.go @@ -1,4 +1,4 @@ -package configs +package userconfig import ( "encoding/json" diff --git a/pkg/cortex/cortex.go b/pkg/cortex/cortex.go index 57fdd0f18d1..36955bcbec1 100644 --- a/pkg/cortex/cortex.go +++ b/pkg/cortex/cortex.go @@ -5,6 +5,8 @@ import ( "fmt" "os" + "github.com/cortexproject/cortex/pkg/configs" + "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/pkg/errors" @@ -81,7 +83,7 @@ type Config struct { Compactor compactor.Config `yaml:"compactor,omitempty"` Ruler ruler.Config `yaml:"ruler,omitempty"` - Configs api.Config `yaml:"configs,omitempty"` + Configs configs.Config `yaml:"configs,omitempty"` Alertmanager alertmanager.MultitenantAlertmanagerConfig `yaml:"alertmanager,omitempty"` RuntimeConfig runtimeconfig.ManagerConfig `yaml:"runtime_config,omitempty"` MemberlistKV memberlist.KVConfig `yaml:"memberlist"` diff --git a/pkg/cortex/modules.go b/pkg/cortex/modules.go index 724e829415b..df09d4b19ab 100644 --- a/pkg/cortex/modules.go +++ b/pkg/cortex/modules.go @@ -522,7 +522,7 @@ func (t *Cortex) initConfigs(cfg *Config) (err error) { return } - t.configAPI = api.New(t.configDB, cfg.Configs) + t.configAPI = api.New(t.configDB, cfg.Configs.API) t.configAPI.RegisterRoutes(t.server.HTTP) return } diff --git a/pkg/ruler/rules/store.go b/pkg/ruler/rules/store.go index 11584ea5d88..6cca7de3768 100644 --- a/pkg/ruler/rules/store.go +++ b/pkg/ruler/rules/store.go @@ -4,7 +4,8 @@ import ( "context" "errors" - "github.com/cortexproject/cortex/pkg/configs" + "github.com/cortexproject/cortex/pkg/configs/userconfig" + "github.com/cortexproject/cortex/pkg/configs/client" legacy_rulefmt "github.com/cortexproject/cortex/pkg/ruler/legacy_rulefmt" @@ -45,7 +46,7 @@ func (l RuleGroupList) Formatted() map[string][]legacy_rulefmt.RuleGroup { // ConfigRuleStore is a concrete implementation of RuleStore that sources rules from the config service type ConfigRuleStore struct { configClient client.Client - since configs.ID + since userconfig.ID ruleGroupList map[string]RuleGroupList } @@ -96,7 +97,7 @@ func (c *ConfigRuleStore) ListAllRuleGroups(ctx context.Context) (map[string]Rul // getLatestConfigID gets the latest configs ID. // max [latest, max (map getID cfgs)] -func getLatestConfigID(cfgs map[string]configs.VersionedRulesConfig, latest configs.ID) configs.ID { +func getLatestConfigID(cfgs map[string]userconfig.VersionedRulesConfig, latest userconfig.ID) userconfig.ID { ret := latest for _, config := range cfgs { if config.ID > ret { diff --git a/pkg/ruler/rules/store_test.go b/pkg/ruler/rules/store_test.go index 445e2726868..775cdab212a 100644 --- a/pkg/ruler/rules/store_test.go +++ b/pkg/ruler/rules/store_test.go @@ -6,24 +6,25 @@ import ( "testing" time "time" + "github.com/cortexproject/cortex/pkg/configs/userconfig" + "github.com/stretchr/testify/assert" - "github.com/cortexproject/cortex/pkg/configs" "github.com/cortexproject/cortex/pkg/configs/client" ) var zeroTime time.Time type MockClient struct { - cfgs map[string]configs.VersionedRulesConfig + cfgs map[string]userconfig.VersionedRulesConfig err error } -func (c *MockClient) GetRules(ctx context.Context, since configs.ID) (map[string]configs.VersionedRulesConfig, error) { +func (c *MockClient) GetRules(ctx context.Context, since userconfig.ID) (map[string]userconfig.VersionedRulesConfig, error) { return c.cfgs, c.err } -func (c *MockClient) GetAlerts(ctx context.Context, since configs.ID) (*client.ConfigsResponse, error) { +func (c *MockClient) GetAlerts(ctx context.Context, since userconfig.ID) (*client.ConfigsResponse, error) { return nil, nil } @@ -40,9 +41,9 @@ func Test_ConfigRuleStoreError(t *testing.T) { } func Test_ConfigRuleStoreReturn(t *testing.T) { - id := configs.ID(10) + id := userconfig.ID(10) mock := &MockClient{ - cfgs: map[string]configs.VersionedRulesConfig{ + cfgs: map[string]userconfig.VersionedRulesConfig{ "user": { ID: id, Config: fakeRuleConfig(), @@ -61,7 +62,7 @@ func Test_ConfigRuleStoreReturn(t *testing.T) { func Test_ConfigRuleStoreDelete(t *testing.T) { mock := &MockClient{ - cfgs: map[string]configs.VersionedRulesConfig{ + cfgs: map[string]userconfig.VersionedRulesConfig{ "user": { ID: 1, Config: fakeRuleConfig(), @@ -74,9 +75,9 @@ func Test_ConfigRuleStoreDelete(t *testing.T) { store := NewConfigRuleStore(mock) _, _ = store.ListAllRuleGroups(context.Background()) - mock.cfgs["user"] = configs.VersionedRulesConfig{ + mock.cfgs["user"] = userconfig.VersionedRulesConfig{ ID: 1, - Config: configs.RulesConfig{}, + Config: userconfig.RulesConfig{}, DeletedAt: time.Unix(0, 1), } @@ -87,7 +88,7 @@ func Test_ConfigRuleStoreDelete(t *testing.T) { func Test_ConfigRuleStoreAppend(t *testing.T) { mock := &MockClient{ - cfgs: map[string]configs.VersionedRulesConfig{ + cfgs: map[string]userconfig.VersionedRulesConfig{ "user": { ID: 1, Config: fakeRuleConfig(), @@ -101,7 +102,7 @@ func Test_ConfigRuleStoreAppend(t *testing.T) { _, _ = store.ListAllRuleGroups(context.Background()) delete(mock.cfgs, "user") - mock.cfgs["user2"] = configs.VersionedRulesConfig{ + mock.cfgs["user2"] = userconfig.VersionedRulesConfig{ ID: 1, Config: fakeRuleConfig(), DeletedAt: zeroTime, @@ -114,7 +115,7 @@ func Test_ConfigRuleStoreAppend(t *testing.T) { func Test_ConfigRuleStoreSinceSet(t *testing.T) { mock := &MockClient{ - cfgs: map[string]configs.VersionedRulesConfig{ + cfgs: map[string]userconfig.VersionedRulesConfig{ "user": { ID: 1, Config: fakeRuleConfig(), @@ -136,32 +137,32 @@ func Test_ConfigRuleStoreSinceSet(t *testing.T) { store := NewConfigRuleStore(mock) _, _ = store.ListAllRuleGroups(context.Background()) - assert.Equal(t, configs.ID(100), store.since) + assert.Equal(t, userconfig.ID(100), store.since) delete(mock.cfgs, "user") delete(mock.cfgs, "user1") - mock.cfgs["user2"] = configs.VersionedRulesConfig{ + mock.cfgs["user2"] = userconfig.VersionedRulesConfig{ ID: 50, Config: fakeRuleConfig(), DeletedAt: zeroTime, } _, _ = store.ListAllRuleGroups(context.Background()) - assert.Equal(t, configs.ID(100), store.since) + assert.Equal(t, userconfig.ID(100), store.since) - mock.cfgs["user2"] = configs.VersionedRulesConfig{ + mock.cfgs["user2"] = userconfig.VersionedRulesConfig{ ID: 101, Config: fakeRuleConfig(), DeletedAt: zeroTime, } _, _ = store.ListAllRuleGroups(context.Background()) - assert.Equal(t, configs.ID(101), store.since) + assert.Equal(t, userconfig.ID(101), store.since) } -func fakeRuleConfig() configs.RulesConfig { - return configs.RulesConfig{ - FormatVersion: configs.RuleFormatV2, +func fakeRuleConfig() userconfig.RulesConfig { + return userconfig.RulesConfig{ + FormatVersion: userconfig.RuleFormatV2, Files: map[string]string{ "test": ` # Config no. 1. From 62e4fd811eccdf04eb4fa306b2a991e2fff3cbf5 Mon Sep 17 00:00:00 2001 From: Wing924 Date: Mon, 2 Mar 2020 13:05:22 +0900 Subject: [PATCH 07/12] fix Signed-off-by: Wing924 --- docs/configuration/config-file-reference.md | 17 +++++++++-------- pkg/configs/client/client.go | 4 ++-- tools/doc-generator/main.go | 7 +++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/configuration/config-file-reference.md b/docs/configuration/config-file-reference.md index 773a81ddf4a..6f360fa18ce 100644 --- a/docs/configuration/config-file-reference.md +++ b/docs/configuration/config-file-reference.md @@ -2082,14 +2082,15 @@ database: # CLI flag: -configs.database.password-file [password_file: | default = ""] -notifications: - # Disable Email notifications for Alertmanager. - # CLI flag: -configs.notifications.disable-email - [disable_email: | default = false] - - # Disable WebHook notifications for Alertmanager. - # CLI flag: -configs.notifications.disable-webhook - [disable_webhook: | default = false] +api: + notifications: + # Disable Email notifications for Alertmanager. + # CLI flag: -configs.notifications.disable-email + [disable_email: | default = false] + + # Disable WebHook notifications for Alertmanager. + # CLI flag: -configs.notifications.disable-webhook + [disable_webhook: | default = false] ``` ### `configstore_config` diff --git a/pkg/configs/client/client.go b/pkg/configs/client/client.go index b8df442a471..6397c67c30d 100644 --- a/pkg/configs/client/client.go +++ b/pkg/configs/client/client.go @@ -28,8 +28,8 @@ type Config struct { // RegisterFlagsWithPrefix adds the flags required to config this to the given FlagSet func (cfg *Config) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) { - f.Var(&cfg.ConfigsAPIURL, prefix+"userconfig.url", "URL of configs API server.") - f.DurationVar(&cfg.ClientTimeout, prefix+"userconfig.client-timeout", 5*time.Second, "Timeout for requests to Weave Cloud configs service.") + f.Var(&cfg.ConfigsAPIURL, prefix+"configs.url", "URL of configs API server.") + f.DurationVar(&cfg.ClientTimeout, prefix+"configs.client-timeout", 5*time.Second, "Timeout for requests to Weave Cloud configs service.") } var configsRequestDuration = instrument.NewHistogramCollector(promauto.NewHistogramVec(prometheus.HistogramOpts{ diff --git a/tools/doc-generator/main.go b/tools/doc-generator/main.go index 9b480b641d0..a26c0eca9d6 100644 --- a/tools/doc-generator/main.go +++ b/tools/doc-generator/main.go @@ -9,14 +9,12 @@ import ( "strings" "text/template" - "github.com/weaveworks/common/server" - "github.com/cortexproject/cortex/pkg/alertmanager" "github.com/cortexproject/cortex/pkg/chunk" "github.com/cortexproject/cortex/pkg/chunk/cache" "github.com/cortexproject/cortex/pkg/chunk/storage" "github.com/cortexproject/cortex/pkg/compactor" - "github.com/cortexproject/cortex/pkg/configs/api" + "github.com/cortexproject/cortex/pkg/configs" config_client "github.com/cortexproject/cortex/pkg/configs/client" "github.com/cortexproject/cortex/pkg/cortex" "github.com/cortexproject/cortex/pkg/distributor" @@ -31,6 +29,7 @@ import ( "github.com/cortexproject/cortex/pkg/ruler" "github.com/cortexproject/cortex/pkg/storage/tsdb" "github.com/cortexproject/cortex/pkg/util/validation" + "github.com/weaveworks/common/server" ) const ( @@ -149,7 +148,7 @@ var ( }, { name: "configs_config", - structType: reflect.TypeOf(api.Config{}), + structType: reflect.TypeOf(configs.Config{}), desc: "The configs_config configures the Cortex Configs DB and API.", }, { From 1dd81f535f80d82e341604149eb745b125aa907a Mon Sep 17 00:00:00 2001 From: Wing924 Date: Mon, 2 Mar 2020 18:50:01 +0900 Subject: [PATCH 08/12] fix Signed-off-by: Wing924 --- CHANGELOG.md | 6 +++--- go.mod | 1 + go.sum | 1 + pkg/configs/api/api.go | 11 +++++++++-- pkg/configs/api/api_test.go | 22 ++++++++++++++++++++++ pkg/configs/api/helpers_test.go | 11 +++++++++++ pkg/configs/db/db.go | 2 +- 7 files changed, 48 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62fbcea8591..d581b5c3ece 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,9 +29,9 @@ * configuration options * `-database.*` -> `-configs.database.*` * config file - * `configdb:` -> `configs:` - * `configdb.migrationsdir:` -> `configs.migrations_dir:` - * `configdb.passwordfile:` -> `configs.password_file:` + * `configdb.uri:` -> `configs.database.uri:` + * `configdb.migrationsdir:` -> `configs.database.migrations_dir:` + * `configdb.passwordfile:` -> `configs.database.password_file:` * [CHANGE] Experimental TSDB: the querier in-memory index cache used by the experimental blocks storage shifted from per-tenant to per-querier. The `-experimental.tsdb.bucket-store.index-cache-size-bytes` now configures the per-querier index cache max size instead of a per-tenant cache and its default has been increased to 1GB. #2189 * [FEATURE] Added a read-only local alertmanager config store using files named corresponding to their tenant id. #2125 * [FEATURE] Added user sub rings to distribute users to a subset of ingesters. #1947 diff --git a/go.mod b/go.mod index ad50eaec3f9..8e1962af6d1 100644 --- a/go.mod +++ b/go.mod @@ -65,6 +65,7 @@ require ( go.uber.org/atomic v1.5.0 golang.org/x/net v0.0.0-20191112182307-2180aed22343 golang.org/x/time v0.0.0-20191024005414-555d28b269f0 + golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 google.golang.org/api v0.14.0 google.golang.org/grpc v1.25.1 gopkg.in/yaml.v2 v2.2.7 diff --git a/go.sum b/go.sum index 87e824fcd96..3a9c79c0e36 100644 --- a/go.sum +++ b/go.sum @@ -980,6 +980,7 @@ golang.org/x/tools v0.0.0-20191111182352-50fa39b762bc/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2 h1:EtTFh6h4SAKemS+CURDMTDIANuduG5zKEXShyy18bGA= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= diff --git a/pkg/configs/api/api.go b/pkg/configs/api/api.go index 81f5f91d863..a1fc58ac3ee 100644 --- a/pkg/configs/api/api.go +++ b/pkg/configs/api/api.go @@ -10,6 +10,8 @@ import ( "net/http" "strconv" + errors "golang.org/x/xerrors" + "github.com/go-kit/kit/log/level" "github.com/gorilla/mux" amconfig "github.com/prometheus/alertmanager/config" @@ -186,6 +188,11 @@ func (a *API) validateAlertmanagerConfig(w http.ResponseWriter, r *http.Request) }) } +var ( + ErrEmailNotificationsAreDisabled = errors.New("email notifications are disabled") + ErrWebhookNotificationsAreDisabled = errors.New("webhook notifications are disabled") +) + func validateAlertmanagerConfig(cfg string, noCfg NotificationsConfig) error { amCfg, err := amconfig.Load(cfg) if err != nil { @@ -194,10 +201,10 @@ func validateAlertmanagerConfig(cfg string, noCfg NotificationsConfig) error { for _, recv := range amCfg.Receivers { if noCfg.DisableEmail && len(recv.EmailConfigs) > 0 { - return fmt.Errorf("email notifications are disabled") + return ErrEmailNotificationsAreDisabled } if noCfg.DisableWebHook && len(recv.WebhookConfigs) > 0 { - return fmt.Errorf("webhook notifications are disabled") + return ErrWebhookNotificationsAreDisabled } } diff --git a/pkg/configs/api/api_test.go b/pkg/configs/api/api_test.go index f0dd969fdaf..5361b9c7747 100644 --- a/pkg/configs/api/api_test.go +++ b/pkg/configs/api/api_test.go @@ -299,3 +299,25 @@ func Test_SetConfig_ValidatesAlertmanagerConfig(t *testing.T) { assert.Contains(t, resp.Body.String(), test.errContains, "test case %d", i) } } + +func Test_SetConfig_ValidatesAlertmanagerConfig_WithEmailEnabled(t *testing.T) { + config := ` + global: + smtp_smarthost: localhost:25 + smtp_from: alertmanager@example.org + route: + receiver: noop + + receivers: + - name: noop + email_configs: + - to: myteam@foobar.org` + setupWithEmailEnabled(t) + defer cleanup(t) + + userID := makeUserID() + cfg := userconfig.Config{AlertmanagerConfig: config} + resp := requestAsUser(t, userID, "POST", "/api/prom/configs/alertmanager", readerFromConfig(t, cfg)) + + assert.Equal(t, http.StatusNoContent, resp.Code) +} diff --git a/pkg/configs/api/helpers_test.go b/pkg/configs/api/helpers_test.go index 3b4de0a10f7..4b21e31ddcb 100644 --- a/pkg/configs/api/helpers_test.go +++ b/pkg/configs/api/helpers_test.go @@ -36,6 +36,17 @@ func setup(t *testing.T) { counter = 0 } +// setup sets up the environment for the tests with email enabled. +func setupWithEmailEnabled(t *testing.T) { + database = dbtest.Setup(t) + app = api.New(database, api.Config{ + Notifications: api.NotificationsConfig{ + DisableEmail: false, + }, + }) + counter = 0 +} + // cleanup cleans up the environment after a test. func cleanup(t *testing.T) { dbtest.Cleanup(t, database) diff --git a/pkg/configs/db/db.go b/pkg/configs/db/db.go index 302ff4862b3..0ec290494c7 100644 --- a/pkg/configs/db/db.go +++ b/pkg/configs/db/db.go @@ -25,7 +25,7 @@ type Config struct { // RegisterFlags adds the flags required to configure this to the given FlagSet. func (cfg *Config) RegisterFlags(f *flag.FlagSet) { f.StringVar(&cfg.URI, "configs.database.uri", "postgres://postgres@configs-db.weave.local/configs?sslmode=disable", "URI where the database can be found (for dev you can use memory://)") - f.StringVar(&cfg.MigrationsDir, "configs.database.migrations", "", "Path where the database migration files can be found") + f.StringVar(&cfg.MigrationsDir, "configs.database.migrations-dir", "", "Path where the database migration files can be found") f.StringVar(&cfg.PasswordFile, "configs.database.password-file", "", "File containing password (username goes in URI)") } From 3672c5026548b247c1dbe05bbbae258508f549b1 Mon Sep 17 00:00:00 2001 From: Wing924 Date: Mon, 2 Mar 2020 18:52:27 +0900 Subject: [PATCH 09/12] fix Signed-off-by: Wing924 --- CHANGELOG.md | 1 + docs/configuration/config-file-reference.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d581b5c3ece..4ae9366989f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ * [CHNAGE] Renamed Configs configuration options. #2187 * configuration options * `-database.*` -> `-configs.database.*` + * `-database.migrations` -> `-configs.database.migrations-dir` * config file * `configdb.uri:` -> `configs.database.uri:` * `configdb.migrationsdir:` -> `configs.database.migrations_dir:` diff --git a/docs/configuration/config-file-reference.md b/docs/configuration/config-file-reference.md index 6f360fa18ce..47fd0a03e99 100644 --- a/docs/configuration/config-file-reference.md +++ b/docs/configuration/config-file-reference.md @@ -2075,7 +2075,7 @@ database: [uri: | default = "postgres://postgres@configs-db.weave.local/configs?sslmode=disable"] # Path where the database migration files can be found - # CLI flag: -configs.database.migrations + # CLI flag: -configs.database.migrations-dir [migrations_dir: | default = ""] # File containing password (username goes in URI) From 13ce0c53449009a07db5d405540f7af8782f93ec Mon Sep 17 00:00:00 2001 From: Wing924 Date: Mon, 2 Mar 2020 19:16:59 +0900 Subject: [PATCH 10/12] fix Signed-off-by: Wing924 --- pkg/configs/api/api_test.go | 6 ++++++ tools/doc-generator/main.go | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/configs/api/api_test.go b/pkg/configs/api/api_test.go index 5361b9c7747..8f18201b40e 100644 --- a/pkg/configs/api/api_test.go +++ b/pkg/configs/api/api_test.go @@ -263,6 +263,9 @@ var amCfgValidationTests = []struct { } func Test_ValidateAlertmanagerConfig(t *testing.T) { + setup(t) + defer cleanup(t) + userID := makeUserID() for i, test := range amCfgValidationTests { resp := requestAsUser(t, userID, "POST", "/api/prom/configs/alertmanager/validate", strings.NewReader(test.config)) @@ -285,6 +288,9 @@ func Test_ValidateAlertmanagerConfig(t *testing.T) { } func Test_SetConfig_ValidatesAlertmanagerConfig(t *testing.T) { + setup(t) + defer cleanup(t) + userID := makeUserID() for i, test := range amCfgValidationTests { cfg := userconfig.Config{AlertmanagerConfig: test.config} diff --git a/tools/doc-generator/main.go b/tools/doc-generator/main.go index a26c0eca9d6..4a53724b1c8 100644 --- a/tools/doc-generator/main.go +++ b/tools/doc-generator/main.go @@ -9,6 +9,8 @@ import ( "strings" "text/template" + "github.com/weaveworks/common/server" + "github.com/cortexproject/cortex/pkg/alertmanager" "github.com/cortexproject/cortex/pkg/chunk" "github.com/cortexproject/cortex/pkg/chunk/cache" @@ -29,7 +31,6 @@ import ( "github.com/cortexproject/cortex/pkg/ruler" "github.com/cortexproject/cortex/pkg/storage/tsdb" "github.com/cortexproject/cortex/pkg/util/validation" - "github.com/weaveworks/common/server" ) const ( From b2522182ee5269746f42659fcc7b8606531fc6ed Mon Sep 17 00:00:00 2001 From: Wing924 Date: Tue, 3 Mar 2020 22:56:13 +0900 Subject: [PATCH 11/12] fix Signed-off-by: Wing924 --- CHANGELOG.md | 2 +- go.mod | 1 - pkg/configs/api/api.go | 13 ++++++------- pkg/configs/api/api_test.go | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f1be03666b..7b185244b58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ * [CHANGE] Updated Prometheus dependency to v2.16.0. This Prometheus version uses Active Query Tracker to limit concurrent queries. In order to keep `-querier.max-concurrent` working, Active Query Tracker is enabled by default, and is configured to store its data to `active-query-tracker` directory (relative to current directory when Cortex started). This can be changed by using `-querier.active-query-tracker-dir` option. Purpose of Active Query Tracker is to log queries that were running when Cortex crashes. This logging happens on next Cortex start. #2088 * [CHANGE] Experimental TSDB: TSDB head compaction interval and concurrency is now configurable (defaults to 1 min interval and 5 concurrent head compactions). New options: `-experimental.tsdb.head-compaction-interval` and `-experimental.tsdb.head-compaction-concurrency`. #2172 * [CHANGE] Remove fluentd-based billing infrastructure and flags such as `-distributor.enable-billing`. #1491 -* [CHNAGE] Renamed Configs configuration options. #2187 +* [CHANGE] Renamed Configs configuration options. #2187 * configuration options * `-database.*` -> `-configs.database.*` * `-database.migrations` -> `-configs.database.migrations-dir` diff --git a/go.mod b/go.mod index 8e1962af6d1..ad50eaec3f9 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,6 @@ require ( go.uber.org/atomic v1.5.0 golang.org/x/net v0.0.0-20191112182307-2180aed22343 golang.org/x/time v0.0.0-20191024005414-555d28b269f0 - golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 google.golang.org/api v0.14.0 google.golang.org/grpc v1.25.1 gopkg.in/yaml.v2 v2.2.7 diff --git a/pkg/configs/api/api.go b/pkg/configs/api/api.go index a1fc58ac3ee..5d4f158dd73 100644 --- a/pkg/configs/api/api.go +++ b/pkg/configs/api/api.go @@ -3,6 +3,7 @@ package api import ( "database/sql" "encoding/json" + "errors" "flag" "fmt" "html/template" @@ -10,8 +11,6 @@ import ( "net/http" "strconv" - errors "golang.org/x/xerrors" - "github.com/go-kit/kit/log/level" "github.com/gorilla/mux" amconfig "github.com/prometheus/alertmanager/config" @@ -22,6 +21,11 @@ import ( "github.com/cortexproject/cortex/pkg/util" ) +var ( + ErrEmailNotificationsAreDisabled = errors.New("email notifications are disabled") + ErrWebhookNotificationsAreDisabled = errors.New("webhook notifications are disabled") +) + // Config configures Configs API type Config struct { Notifications NotificationsConfig `yaml:"notifications"` @@ -188,11 +192,6 @@ func (a *API) validateAlertmanagerConfig(w http.ResponseWriter, r *http.Request) }) } -var ( - ErrEmailNotificationsAreDisabled = errors.New("email notifications are disabled") - ErrWebhookNotificationsAreDisabled = errors.New("webhook notifications are disabled") -) - func validateAlertmanagerConfig(cfg string, noCfg NotificationsConfig) error { amCfg, err := amconfig.Load(cfg) if err != nil { diff --git a/pkg/configs/api/api_test.go b/pkg/configs/api/api_test.go index 8f18201b40e..3d84fc18ee8 100644 --- a/pkg/configs/api/api_test.go +++ b/pkg/configs/api/api_test.go @@ -245,7 +245,7 @@ var amCfgValidationTests = []struct { email_configs: - to: myteam@foobar.org`, shouldFail: true, - errContains: "email notifications are disabled", + errContains: api.ErrEmailNotificationsAreDisabled.Error(), }, { config: ` global: From 91dcdc98fa2a0eb83988e98edc505e271ee0a745 Mon Sep 17 00:00:00 2001 From: Wing924 Date: Tue, 3 Mar 2020 23:18:10 +0900 Subject: [PATCH 12/12] fix Signed-off-by: Wing924 --- go.sum | 1 - 1 file changed, 1 deletion(-) diff --git a/go.sum b/go.sum index a9653b8808a..cbc4a88eb4b 100644 --- a/go.sum +++ b/go.sum @@ -983,7 +983,6 @@ golang.org/x/tools v0.0.0-20191111182352-50fa39b762bc/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2 h1:EtTFh6h4SAKemS+CURDMTDIANuduG5zKEXShyy18bGA= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=