Skip to content

Instantly share code, notes, and snippets.

@grepory
Created October 3, 2018 18:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grepory/be38b42e8a8a41a5d9165766b9e2ed7e to your computer and use it in GitHub Desktop.
Save grepory/be38b42e8a8a41a5d9165766b9e2ed7e to your computer and use it in GitHub Desktop.
package routes
import (
"fmt"
"net/http"
"path"
restful "github.com/emicklei/go-restful"
"github.com/emicklei/go-restful-openapi"
"github.com/grepory/storage/apis/meta"
"github.com/grepory/storage/server"
"github.com/grepory/storage/storage"
)
const (
apiRoot = "/api"
)
type ServiceBuilder interface {
Build(obj meta.Object, strategy server.RestStrategy) *restful.WebService
}
func NewRestServiceBuilder(store storage.Store) *RestServiceBuilder {
return &RestServiceBuilder{
store: store,
}
}
type RestServiceBuilder struct {
store storage.Store
}
func (b RestServiceBuilder) Build(obj meta.Object, strategy server.RestStrategy) (ws *restful.WebService) {
gvk := meta.GetGroupVersionKind(obj)
if gvk == nil {
return nil
}
path := path.Join(apiRoot, gvk.GetKind())
ws.Path(path).
ApiVersion(gvk.GetVersion()).
Consumes(restful.MIME_JSON).
Produces(restful.MIME_JSON)
tags := []string{gvk.GetKind()}
ws.Route(ws.GET("/{name}").To(b.getObject(strategy)).
Doc(fmt.Sprintf("get a %s", gvk.GetKind())).
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.PathParameter("name", fmt.Sprintf("name of the %s", gvk.GetKind())).DataType("string")).
Writes(obj).
Returns(http.StatusOK, http.StatusText(http.StatusOK), obj).
Returns(http.StatusNotFound, http.StatusText(http.StatusNotFound), nil))
ws.Route(ws.POST("").To(b.createObject(strategy)).
Doc("create a Simple").
Metadata(restfulspec.KeyOpenAPITags, tags).
Reads(obj))
return ws
}
func (b RestServiceBuilder) getObject(strategy server.RestStrategy) restful.RouteFunction {
return func(req *restful.Request, resp *restful.Response) {
obj := strategy.PrepareForUpdate()
name := req.PathParameter("name")
if err := b.store.Get(name, obj); err != nil {
if err == storage.ErrNotFound {
resp.WriteError(http.StatusNotFound, err)
}
resp.WriteError(http.StatusInternalServerError, err)
}
resp.WriteEntity(obj)
}
}
func (b RestServiceBuilder) createObject(strategy server.RestStrategy) restful.RouteFunction {
return func(req *restful.Request, resp *restful.Response) {
// returns meta.Object
obj := strategy.PrepareForUpdate()
if err := req.ReadEntity(obj); err != nil {
resp.WriteError(http.StatusBadRequest, err)
}
if err := strategy.Validate(obj); err != nil {
resp.WriteError(http.StatusBadRequest, err)
}
if err := b.store.Create(obj.GetName(), obj); err != nil {
resp.WriteError(http.StatusNotFound, err)
}
resp.WriteEntity(obj)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment