Files
2020-10-15 09:44:04 +02:00

105 lines
2.8 KiB
Go

package api
import (
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/sirupsen/logrus"
"github.com/traefik/mesh/v2/pkg/provider"
"github.com/traefik/mesh/v2/pkg/safe"
"github.com/traefik/mesh/v2/pkg/topology"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
)
// API is an implementation of an api.
type API struct {
http.Server
readiness *safe.Safe
configuration *safe.Safe
topology *safe.Safe
namespace string
logger logrus.FieldLogger
}
// NewAPI creates a new api.
func NewAPI(logger logrus.FieldLogger, port int32, host, namespace string) *API {
router := mux.NewRouter()
api := &API{
Server: http.Server{
Addr: fmt.Sprintf("%s:%d", host, port),
ReadTimeout: 5 * time.Second,
WriteTimeout: 5 * time.Second,
Handler: router,
},
configuration: safe.New(provider.NewDefaultDynamicConfig()),
topology: safe.New(topology.NewTopology()),
readiness: safe.New(false),
namespace: namespace,
logger: logger,
}
router.HandleFunc("/api/configuration", api.getConfiguration)
router.HandleFunc("/api/topology", api.getTopology)
router.HandleFunc("/api/ready", api.getReadiness)
return api
}
// SetReadiness sets the readiness flag in the API.
func (a *API) SetReadiness(isReady bool) {
a.readiness.Set(isReady)
a.logger.Debugf("API readiness: %t", isReady)
}
// SetConfiguration sets the current dynamic configuration.
func (a *API) SetConfiguration(cfg *dynamic.Configuration) {
a.configuration.Set(cfg)
}
// SetTopology sets the current topology.
func (a *API) SetTopology(topo *topology.Topology) {
a.topology.Set(topo)
}
// getConfiguration returns the current configuration.
func (a *API) getConfiguration(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(a.configuration.Get()); err != nil {
a.logger.Errorf("Unable to serialize configuration: %v", err)
http.Error(w, "", http.StatusInternalServerError)
}
}
// getTopology returns the current topology.
func (a *API) getTopology(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(a.topology.Get()); err != nil {
a.logger.Errorf("Unable to serialize topology: %v", err)
http.Error(w, "", http.StatusInternalServerError)
}
}
// getReadiness returns the current readiness value, and sets the status code to 500 if not ready.
func (a *API) getReadiness(w http.ResponseWriter, _ *http.Request) {
isReady, _ := a.readiness.Get().(bool)
if !isReady {
http.Error(w, "", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(isReady); err != nil {
a.logger.Errorf("Unable to serialize readiness: %v", err)
http.Error(w, "", http.StatusInternalServerError)
}
}