Simplify configapi

pull/89/head
Aloïs Micard 3 years ago
parent b7ad2097e4
commit 51f12b4cba
No known key found for this signature in database
GPG Key ID: 1A0EB82F071F5EFE

@ -1,11 +0,0 @@
package api
//go:generate mockgen -destination=../api_mock/api_mock.go -package=api_mock . ConfigAPI
// ConfigAPI expose the functionality of the config API
type ConfigAPI interface {
// Get value of given key
Get(key string) ([]byte, error)
// Set value of given key
Set(key string, value []byte) error
}

@ -2,9 +2,7 @@ package configapi
import (
"fmt"
"github.com/creekorful/trandoshan/internal/configapi/api"
"github.com/creekorful/trandoshan/internal/configapi/database"
"github.com/creekorful/trandoshan/internal/configapi/service"
"github.com/creekorful/trandoshan/internal/event"
"github.com/creekorful/trandoshan/internal/logging"
"github.com/creekorful/trandoshan/internal/util"
@ -56,14 +54,12 @@ func execute(ctx *cli.Context) error {
return err
}
// Create the ConfigAPI service
// Create database connection
db, err := database.NewRedisDatabase(ctx.String("db-uri"))
if err != nil {
return err
}
s, err := service.NewService(db, pub)
// Parse default values
defaultValues := map[string]string{}
for _, value := range ctx.StringSlice("default-value") {
@ -76,14 +72,15 @@ func execute(ctx *cli.Context) error {
// Set default values if needed
if len(defaultValues) > 0 {
if err := setDefaultValues(s, defaultValues); err != nil {
if err := setDefaultValues(db, defaultValues); err != nil {
log.Err(err).Msg("error while setting default values")
return err
}
}
state := state{
api: s,
db: db,
pub: pub,
}
r := mux.NewRouter()
@ -103,14 +100,17 @@ func execute(ctx *cli.Context) error {
}
type state struct {
api api.ConfigAPI
db database.Database
pub event.Publisher
}
func (state *state) getConfiguration(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
key := vars["key"]
b, err := state.api.Get(key)
log.Debug().Str("key", key).Msg("Getting key")
b, err := state.db.Get(key)
if err != nil {
log.Err(err).Msg("error while retrieving configuration")
w.WriteHeader(http.StatusInternalServerError)
@ -132,17 +132,28 @@ func (state *state) setConfiguration(w http.ResponseWriter, r *http.Request) {
return
}
if err := state.api.Set(key, b); err != nil {
log.Debug().Str("key", key).Bytes("value", b).Msg("Setting key")
if err := state.db.Set(key, b); err != nil {
log.Err(err).Msg("error while setting configuration")
w.WriteHeader(http.StatusInternalServerError)
return
}
// publish event to notify config changed
if err := state.pub.PublishJSON(event.ConfigExchange, event.RawMessage{
Body: b,
Headers: map[string]interface{}{"Config-Key": key},
}); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(b)
}
func setDefaultValues(service api.ConfigAPI, values map[string]string) error {
func setDefaultValues(service database.Database, values map[string]string) error {
for key, value := range values {
if _, err := service.Get(key); err == redis.Nil {
if err := service.Set(key, []byte(value)); err != nil {

@ -1,7 +1,9 @@
package configapi
import (
"github.com/creekorful/trandoshan/internal/configapi/api_mock"
"github.com/creekorful/trandoshan/internal/configapi/database_mock"
"github.com/creekorful/trandoshan/internal/event"
"github.com/creekorful/trandoshan/internal/event_mock"
"github.com/golang/mock/gomock"
"github.com/gorilla/mux"
"io/ioutil"
@ -15,15 +17,15 @@ func TestGetConfiguration(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
apiMock := api_mock.NewMockConfigAPI(mockCtrl)
apiMock.EXPECT().Get("hello").Return([]byte("{\"ttl\": \"10s\"}"), nil)
dbMock := database_mock.NewMockDatabase(mockCtrl)
dbMock.EXPECT().Get("hello").Return([]byte("{\"ttl\": \"10s\"}"), nil)
req := httptest.NewRequest(http.MethodGet, "/config/hello", nil)
req = mux.SetURLVars(req, map[string]string{"key": "hello"})
rec := httptest.NewRecorder()
s := state{api: apiMock}
s := state{db: dbMock}
s.getConfiguration(rec, req)
if rec.Code != http.StatusOK {
@ -47,15 +49,21 @@ func TestSetConfiguration(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
apiMock := api_mock.NewMockConfigAPI(mockCtrl)
apiMock.EXPECT().Set("hello", []byte("{\"ttl\": \"10s\"}")).Return(nil)
dbMock := database_mock.NewMockDatabase(mockCtrl)
pubMock := event_mock.NewMockPublisher(mockCtrl)
dbMock.EXPECT().Set("hello", []byte("{\"ttl\": \"10s\"}")).Return(nil)
pubMock.EXPECT().PublishJSON("config", event.RawMessage{
Body: []byte("{\"ttl\": \"10s\"}"),
Headers: map[string]interface{}{"Config-Key": "hello"},
}).Return(nil)
req := httptest.NewRequest(http.MethodPut, "/config/hello", strings.NewReader("{\"ttl\": \"10s\"}"))
req = mux.SetURLVars(req, map[string]string{"key": "hello"})
rec := httptest.NewRecorder()
s := state{api: apiMock}
s := state{db: dbMock, pub: pubMock}
s.setConfiguration(rec, req)
if rec.Code != http.StatusOK {

@ -1,26 +0,0 @@
package database
import "sync"
// MemoryDatabase is an memory only database structure
type MemoryDatabase struct {
values map[string][]byte
mutex sync.Mutex
}
// Get value using his key
func (md *MemoryDatabase) Get(key string) ([]byte, error) {
md.mutex.Lock()
defer md.mutex.Unlock()
return md.values[key], nil
}
// Set value for given key
func (md *MemoryDatabase) Set(key string, value []byte) error {
md.mutex.Lock()
defer md.mutex.Unlock()
md.values[key] = value
return nil
}

@ -1,42 +0,0 @@
package service
import (
"github.com/creekorful/trandoshan/internal/configapi/api"
"github.com/creekorful/trandoshan/internal/configapi/database"
"github.com/creekorful/trandoshan/internal/event"
"github.com/rs/zerolog/log"
)
type service struct {
db database.Database
pub event.Publisher
}
// NewService create a new service exposing the ConfigAPI features
func NewService(db database.Database, pub event.Publisher) (api.ConfigAPI, error) {
return &service{
db: db,
pub: pub,
}, nil
}
// Get config using his key
func (s *service) Get(key string) ([]byte, error) {
log.Debug().Str("key", key).Msg("Getting key")
return s.db.Get(key)
}
// Set config value
func (s *service) Set(key string, value []byte) error {
log.Debug().Str("key", key).Bytes("value", value).Msg("Setting key")
if err := s.db.Set(key, value); err != nil {
return err
}
// publish event to notify config changed
return s.pub.PublishJSON(event.ConfigExchange, event.RawMessage{
Body: value,
Headers: map[string]interface{}{"Config-Key": key},
})
}

@ -1,52 +0,0 @@
package service
import (
"github.com/creekorful/trandoshan/internal/configapi/database_mock"
"github.com/creekorful/trandoshan/internal/event"
"github.com/creekorful/trandoshan/internal/event_mock"
"github.com/golang/mock/gomock"
"testing"
)
func TestService_Get(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
dbMock := database_mock.NewMockDatabase(mockCtrl)
dbMock.EXPECT().Get("test").Return([]byte("hello"), nil)
s := service{
db: dbMock,
}
val, err := s.Get("test")
if err != nil {
t.FailNow()
}
if string(val) != "hello" {
t.Fail()
}
}
func TestService_Set(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
dbMock := database_mock.NewMockDatabase(mockCtrl)
pubMock := event_mock.NewMockPublisher(mockCtrl)
dbMock.EXPECT().Set("test-key", []byte("hello")).Return(nil)
pubMock.EXPECT().PublishJSON("config", event.RawMessage{
Body: []byte("hello"),
Headers: map[string]interface{}{"Config-Key": "test-key"},
}).Return(nil)
s := service{
db: dbMock,
pub: pubMock,
}
if err := s.Set("test-key", []byte("hello")); err != nil {
t.Fail()
}
}
Loading…
Cancel
Save