215 lines
4.7 KiB
Go
215 lines
4.7 KiB
Go
|
|
package api
|
||
|
|
|
||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
"sync"
|
||
|
|
"os"
|
||
|
|
"io/ioutil"
|
||
|
|
"log"
|
||
|
|
"encoding/json"
|
||
|
|
|
||
|
|
"github.com/labstack/echo/v4"
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
type Rediops struct {
|
||
|
|
Lock sync.Mutex
|
||
|
|
ConfigFilename string
|
||
|
|
DataFolder string
|
||
|
|
ConfigFolder string
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewRediops(configFolder string, configFilename string, dataFolder string) *Rediops {
|
||
|
|
|
||
|
|
return &Rediops{
|
||
|
|
ConfigFolder: configFolder,
|
||
|
|
ConfigFilename: configFilename,
|
||
|
|
DataFolder: dataFolder,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// A common error payload returned
|
||
|
|
// when the response code is not 2xx
|
||
|
|
type ErrorModel struct {
|
||
|
|
// Error description, that shuld be less technical
|
||
|
|
// and more user orientated where possible
|
||
|
|
Message *string `json:"message,omitempty"`
|
||
|
|
Resolution *string `json:"resolution,omitempty"`
|
||
|
|
|
||
|
|
// Status code as a string
|
||
|
|
Status *string `json:"status,omitempty"`
|
||
|
|
|
||
|
|
// Numerical value of the status code
|
||
|
|
StatusCode *int `json:"statusCode,omitempty"`
|
||
|
|
|
||
|
|
// Technical information for the error.
|
||
|
|
//
|
||
|
|
// This must not contain sensitive information
|
||
|
|
Technical *string `json:"technical,omitempty"`
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
func sendGeneralError(ctx echo.Context, code int, message string) error {
|
||
|
|
|
||
|
|
var s = ""
|
||
|
|
|
||
|
|
genErr := ErrorModel{
|
||
|
|
Message: &message,
|
||
|
|
Status: &s,
|
||
|
|
StatusCode: &code,
|
||
|
|
}
|
||
|
|
|
||
|
|
err := ctx.JSON(code, genErr)
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
func (ro *Rediops) GetHealth(ctx echo.Context) error {
|
||
|
|
|
||
|
|
ro.Lock.Lock()
|
||
|
|
defer ro.Lock.Unlock()
|
||
|
|
|
||
|
|
var item = HealthResponse {
|
||
|
|
Status: "OK",
|
||
|
|
Message: "Service available",
|
||
|
|
}
|
||
|
|
|
||
|
|
return ctx.JSON(http.StatusOK, item)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fetch the DevOps information
|
||
|
|
// (GET /.well-known/devops)
|
||
|
|
func (ro *Rediops) GetWellKnownDevopsJson(ctx echo.Context) error {
|
||
|
|
|
||
|
|
// Check if the corresponding file exists
|
||
|
|
fileName := ro.DataFolder + "/devops.json"
|
||
|
|
if _, err := os.Stat(fileName); err == nil {
|
||
|
|
var item = DevopsModel {}
|
||
|
|
|
||
|
|
content, err := ioutil.ReadFile(fileName)
|
||
|
|
if err != nil {
|
||
|
|
log.Fatal("Error when opening file: ", err)
|
||
|
|
return sendGeneralError(ctx, http.StatusInternalServerError ,
|
||
|
|
"Internal server error")
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(content, &item)
|
||
|
|
if err != nil {
|
||
|
|
log.Fatal("Error during Unmarshal(): ", err)
|
||
|
|
return sendGeneralError(ctx, http.StatusInternalServerError ,
|
||
|
|
"Internal server error")
|
||
|
|
}
|
||
|
|
|
||
|
|
return ctx.JSON(http.StatusOK, item)
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
return sendGeneralError(ctx, http.StatusNotFound,
|
||
|
|
"devops.json not found")
|
||
|
|
}
|
||
|
|
|
||
|
|
// List matching captured resources
|
||
|
|
// (GET /devops/)
|
||
|
|
func (ro *Rediops) GetDevops(ctx echo.Context, params GetDevopsParams) error {
|
||
|
|
|
||
|
|
|
||
|
|
var ilist = []DevopsbriefModel {}
|
||
|
|
|
||
|
|
// Check if the corresponding folder exists
|
||
|
|
if _, err := os.Stat(ro.DataFolder); err == nil {
|
||
|
|
|
||
|
|
files, err := ioutil.ReadDir(ro.DataFolder)
|
||
|
|
if err != nil {
|
||
|
|
log.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, file := range files {
|
||
|
|
|
||
|
|
if (!file.IsDir() && (file.Name() != "devops.json")) {
|
||
|
|
content, err := ioutil.ReadFile(ro.DataFolder + "/"+ file.Name())
|
||
|
|
if err != nil {
|
||
|
|
log.Printf("Error when opening file: %s", err)
|
||
|
|
return sendGeneralError(ctx, http.StatusInternalServerError ,
|
||
|
|
"Internal server error")
|
||
|
|
}
|
||
|
|
|
||
|
|
var item = DevopsModel {}
|
||
|
|
err = json.Unmarshal(content, &item)
|
||
|
|
if err != nil {
|
||
|
|
log.Printf("Error during Unmarshal(): %s", err)
|
||
|
|
return sendGeneralError(ctx, http.StatusInternalServerError ,
|
||
|
|
"Internal server error")
|
||
|
|
}
|
||
|
|
|
||
|
|
var brief = DevopsbriefModel {
|
||
|
|
Name: item.Name,
|
||
|
|
Version: item.Version,
|
||
|
|
}
|
||
|
|
brief.UniqueId = *item.UniqueId
|
||
|
|
brief.Guide = *item.Guide
|
||
|
|
brief.Self = "/devops/"+brief.UniqueId
|
||
|
|
|
||
|
|
ilist = append(ilist, brief)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return ctx.JSON(http.StatusOK, ilist)
|
||
|
|
}
|
||
|
|
|
||
|
|
return sendGeneralError(ctx, http.StatusNotFound,
|
||
|
|
"Not found")
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// (DELETE /devops/{id})
|
||
|
|
func (ro *Rediops) DeleteDevopsId(ctx echo.Context, id string) error {
|
||
|
|
|
||
|
|
return sendGeneralError(ctx, http.StatusNotFound,
|
||
|
|
"Not supported")
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fetch the Devops resource
|
||
|
|
// (GET /devops/{id})
|
||
|
|
func (ro *Rediops) GetDevopsId(ctx echo.Context, id string) error {
|
||
|
|
|
||
|
|
|
||
|
|
// Check if the corresponding file exists
|
||
|
|
fileName := ro.DataFolder + "/"+ id + ".json"
|
||
|
|
if _, err := os.Stat(fileName); err == nil {
|
||
|
|
var item = DevopsModel {}
|
||
|
|
|
||
|
|
content, err := ioutil.ReadFile(fileName)
|
||
|
|
if err != nil {
|
||
|
|
log.Printf("Error when opening file: %s", err)
|
||
|
|
return sendGeneralError(ctx, http.StatusInternalServerError ,
|
||
|
|
"Internal server error")
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(content, &item)
|
||
|
|
if err != nil {
|
||
|
|
log.Printf("Error during Unmarshal(): %s", err)
|
||
|
|
return sendGeneralError(ctx, http.StatusInternalServerError ,
|
||
|
|
"Internal server error")
|
||
|
|
}
|
||
|
|
|
||
|
|
return ctx.JSON(http.StatusOK, item)
|
||
|
|
}
|
||
|
|
|
||
|
|
return sendGeneralError(ctx, http.StatusNotFound,
|
||
|
|
(id + " not found"))
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Update the DevOps resource
|
||
|
|
// (POST /devops/{id})
|
||
|
|
func (ro *Rediops) PostDevopsId(ctx echo.Context, id string) error {
|
||
|
|
|
||
|
|
return sendGeneralError(ctx, http.StatusNotFound,
|
||
|
|
"Not supported")
|
||
|
|
|
||
|
|
}
|