diff --git a/VERSION b/VERSION index 1cc5f65..26aaba0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.0 \ No newline at end of file +1.2.0 diff --git a/src/backend.go b/src/backend.go index 60f0666..2979199 100644 --- a/src/backend.go +++ b/src/backend.go @@ -10,7 +10,9 @@ import ( // and forward requests from frontend type Backend interface { IsPrimary() (bool, error) + IsReadWrite() (bool, error) IsReplica() (bool, error) + IsReadOnly() (bool, error) } // NewBackend creates a backend from a driver, a connection string @@ -90,12 +92,22 @@ func (b HTTPBackend) request(key string) (bool, error) { return state.(bool), nil } -// IsPrimary will call /master route on patroni API +// IsPrimary will call /primary route on patroni API func (b HTTPBackend) IsPrimary() (bool, error) { - return b.request("master") + return b.request("primary") +} + +// IsReadWrite will call /read-write route on patroni API +func (b HTTPBackend) IsReadWrite() (bool, error) { + return b.request("read-write") } // IsReplica will call /replica route on patroni API func (b HTTPBackend) IsReplica() (bool, error) { return b.request("replica") } + +// IsReadOnly will call /read-only route on patroni API +func (b HTTPBackend) IsReadOnly() (bool, error) { + return b.request("read-only") +} diff --git a/src/frontend.go b/src/frontend.go index f9944ea..f937044 100644 --- a/src/frontend.go +++ b/src/frontend.go @@ -34,7 +34,10 @@ func (f *Frontend) Start() error { Debug("registering routes") r.HandleFunc("/health", HealthHandler).Methods("GET") r.HandleFunc("/master", PrimaryHandler).Methods("GET", "OPTIONS") + r.HandleFunc("/primary", PrimaryHandler).Methods("GET", "OPTIONS") + r.HandleFunc("/read-write", ReadWriteHandler).Methods("GET", "OPTIONS") r.HandleFunc("/replica", ReplicaHandler).Methods("GET", "OPTIONS") + r.HandleFunc("/read-only", ReadOnlyHandler).Methods("GET", "OPTIONS") Info("listening on %s", f) var err error @@ -148,6 +151,24 @@ func PrimaryHandler(w http.ResponseWriter, r *http.Request) { io.WriteString(w, message) } +// ReadWriteHandler exposes read-write status +func ReadWriteHandler(w http.ResponseWriter, r *http.Request) { + var message string + var status int + readWrite, err := backend.IsReadWrite() + if err != nil { + message = fmt.Sprintf("{\"error\":\"%v\"}", err) + status = http.StatusServiceUnavailable + } + message = fmt.Sprintf("{\"read-write\":%t}", readWrite) + status = http.StatusServiceUnavailable + if readWrite { + status = http.StatusOK + } + w.WriteHeader(status) + io.WriteString(w, message) +} + // ReplicaHandler exposes replica status func ReplicaHandler(w http.ResponseWriter, r *http.Request) { var message string @@ -166,6 +187,24 @@ func ReplicaHandler(w http.ResponseWriter, r *http.Request) { io.WriteString(w, message) } +// ReadOnlyHandler exposes read-only status +func ReadOnlyHandler(w http.ResponseWriter, r *http.Request) { + var message string + var status int + readOnly, err := backend.IsReadOnly() + if err != nil { + message = fmt.Sprintf("{\"error\":\"%v\"}", err) + status = http.StatusServiceUnavailable + } + message = fmt.Sprintf("{\"read-only\":%t}", readOnly) + status = http.StatusServiceUnavailable + if readOnly { + status = http.StatusOK + } + w.WriteHeader(status) + io.WriteString(w, message) +} + // Store TLS ciphers map from string to constant // See full list at https://golang.org/pkg/crypto/tls/#pkg-constants var tlsCiphers = map[string]uint16{