diff --git a/README.md b/README.md index 1f6a49cf2e77d21e0416a701662eda9aa5148fef..bf5b313b728f09fdc087ec1ddeaf029cf3a3a4b4 100644 --- a/README.md +++ b/README.md @@ -63,12 +63,13 @@ issues in the projects you specify in the config file. * CONFIG_DIR - The directory the application should look for config.yaml in. * REDIS_URL - The URL of the Redis host e.g. `redis:6379` * REDIS_PASSWORD - Password for Redis, if an empty password is required set to `REDIS_PASSWORD=` +* USE_SENTINEL - If set the REDIS_URL will be treated as a sentinel and the current master acquired via the sentinel. ### Run it #### Via Docker ```bash -docker run -e GITLAB_API_TOKEN=<INSERT_TOKEN> -e CONFIG_DIR=/app -v REDIS_URL=<REDIS_URL> -v REDIS_PASSWORD=<REDIS_PASSWORD> -v <PATH_TO_CONFIG_DIR>/config adamhf/rss-sync:latest +docker run -e GITLAB_API_TOKEN=<INSERT_TOKEN> -e CONFIG_DIR=/app -v REDIS_URL=<REDIS_URL> -v REDIS_PASSWORD=<REDIS_PASSWORD> -v ${PWD}:/config adamhf/rss-sync:latest ``` #### Via docker-compose @@ -81,6 +82,9 @@ Two metrics (above and beyond what are exposed by the Go Prometheus library) are * last_run_time - The time of the last feed checks, useful for creating alerts to check for successful runs. * issues_created - The total number of issues created in Gitlab, useful to check for runaways. +## Healthz Endpoint +A /healthz endpoint is exposed on :8081/healthz which will fail if it is unable to connect to Redis. + ## Example Issues ### GKE Release Notes Feed URL: https://cloud.google.com/feeds/kubernetes-engine-release-notes.xml diff --git a/main.go b/main.go index 140ad83a0006f5773fc926600a74438dab12dca0..654416b702ff590dbd350af43b60e9686954ffc0 100644 --- a/main.go +++ b/main.go @@ -42,6 +42,7 @@ type EnvValues struct { RedisPassword string ConfDir string GitlabAPIKey string + UseSentinel bool } func hasExistingGitlabIssue(guid string, projectID int, gitlabClient *gitlab.Client) bool { @@ -84,7 +85,7 @@ func (feed Feed) checkFeed(redisClient *redis.Client, gitlabClient *gitlab.Clien var oldArticle []*gofeed.Item for _, item := range rss.Items { found := redisClient.SIsMember(feed.ID, item.GUID).Val() - if found == true { + if found { oldArticle = append(oldArticle, item) } else { newArticle = append(newArticle, item) @@ -187,11 +188,20 @@ func initialise(env EnvValues) (redisClient *redis.Client, client *gitlab.Client client = gitlab.NewClient(nil, env.GitlabAPIKey) config = readConfig(path.Join(env.ConfDir, "config.yaml")) - redisClient = redis.NewClient(&redis.Options{ - Addr: env.RedisURL, - Password: env.RedisPassword, - DB: 0, // use default DB - }) + if !env.UseSentinel { + redisClient = redis.NewClient(&redis.Options{ + Addr: env.RedisURL, + Password: env.RedisPassword, + DB: 0, // use default DB + }) + } else { + redisClient = redis.NewFailoverClient(&redis.FailoverOptions{ + SentinelAddrs: []string{env.RedisURL}, + Password: env.RedisPassword, + MasterName: "mymaster", + DB: 0, // use default DB + }) + } if err := redisClient.Ping().Err(); err != nil { panic(fmt.Sprintf("Unable to connect to Redis @ %s", env.RedisURL)) @@ -205,7 +215,7 @@ func initialise(env EnvValues) (redisClient *redis.Client, client *gitlab.Client func main() { env := readEnv() redisClient, gitlabClient, config := initialise(env) - + go checkLiveliness(redisClient) go func() { for { log.Printf("Running checks at %s\n", time.Now().Format(time.RFC850)) @@ -224,6 +234,8 @@ func main() { func readEnv() EnvValues { var gitlabPAToken, configDir, redisURL, redisPassword string + useSentinel := false + if envGitlabAPIToken := os.Getenv("GITLAB_API_TOKEN"); envGitlabAPIToken == "" { panic("Could not find GITLAB_API_TOKEN specified as an environment variable") } else { @@ -247,10 +259,33 @@ func readEnv() EnvValues { redisPassword = envRedisPassword } + _, hasRedisSentinel := os.LookupEnv("USE_SENTINEL") + if hasRedisSentinel { + log.Printf("Running in sentinel mode") + useSentinel = true + } + return EnvValues{ RedisURL: redisURL, RedisPassword: redisPassword, ConfDir: configDir, GitlabAPIKey: gitlabPAToken, + UseSentinel: useSentinel, + } +} + +func checkLiveliness(client *redis.Client) { + http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { + if err := client.Ping().Err(); err != nil { + http.Error(w, "Unable to connect to the redis master", http.StatusInternalServerError) + } else { + fmt.Fprintf(w, "All is well!") + } + }) + + err := http.ListenAndServe(":8081", nil) + if err != nil { + log.Printf("Unable to start /healthz webserver") } + }