- implement simulator endpoints

- add field for simulation models to simulator models and adapt methods for adding/updating a model
- minor renaming of test functions
This commit is contained in:
Sonja Happ 2019-06-18 13:55:10 +02:00
parent e820d25aae
commit 86e380c85e
8 changed files with 262 additions and 37 deletions

View file

@ -100,6 +100,8 @@ type Simulator struct {
Properties string
// Raw properties of simulator as JSON string
RawProperties string
// SimulationModels in which the simulator is used
SimulationModels []SimulationModel
}
// Visualization data model

View file

@ -137,7 +137,6 @@ func updateSignal(c *gin.Context) {
"message": "OK.",
})
}
}
// getSignal godoc

View file

@ -109,7 +109,7 @@ var msgInSignalC = common.ResponseMsgSignal{
}
// Test /models endpoints
func TestSimulationModelEndpoints(t *testing.T) {
func TestSignalEndpoints(t *testing.T) {
db := common.DummyInitDB()
defer db.Close()

View file

@ -45,6 +45,13 @@ func (m *SimulationModel) addToSimulation() error {
var simltr simulator.Simulator
err = simltr.ByID(m.SimulatorID)
err = db.Model(m).Association("Simulator").Append(&simltr).Error
if err != nil {
return err
}
err = db.Model(&simltr).Association("SimulationModels").Append(m).Error
if err != nil {
return err
}
// associate simulation model with simulation
err = db.Model(&sim).Association("SimulationModels").Append(m).Error
@ -58,11 +65,26 @@ func (m *SimulationModel) Update(modifiedSimulationModel SimulationModel) error
if m.SimulatorID != modifiedSimulationModel.SimulatorID {
// update simulator
var s simulator.Simulator
var s_old simulator.Simulator
err := s.ByID(modifiedSimulationModel.SimulatorID)
if err != nil {
return err
}
err = s_old.ByID(m.SimulatorID)
if err != nil {
return err
}
err = db.Model(m).Association("Simulator").Replace(s).Error
if err != nil {
return err
}
// remove simulation model from old simulator
err = db.Model(&s_old).Association("SimulationModels").Delete(m).Error
if err != nil {
return err
}
// add simulation model to new simulator
err = db.Model(&s).Association("SimulationModels").Append(m).Error
}

View file

@ -1,7 +1,9 @@
package simulator
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
@ -9,17 +11,18 @@ import (
)
func RegisterSimulatorEndpoints(r *gin.RouterGroup) {
r.GET("", GetSimulators)
r.POST("", AddSimulator)
r.PUT("/:simulatorID", UpdateSimulator)
r.GET("/:simulatorID", GetSimulator)
r.DELETE("/:simulatorID", DeleteSimulator)
r.POST("/:simulatorID/action", SendActionToSimulator)
r.GET("", getSimulators)
r.POST("", addSimulator)
r.PUT("/:simulatorID", updateSimulator)
r.GET("/:simulatorID", getSimulator)
r.DELETE("/:simulatorID", deleteSimulator)
r.GET("/:simulatorID/models", getModelsOfSimulator)
r.POST("/:simulatorID/action", sendActionToSimulator)
}
// GetSimulators godoc
// getSimulators godoc
// @Summary Get all simulators
// @ID GetSimulators
// @ID getSimulators
// @Tags simulators
// @Produce json
// @Success 200 {array} common.SimulatorResponse "Simulator parameters requested by user"
@ -28,10 +31,17 @@ func RegisterSimulatorEndpoints(r *gin.RouterGroup) {
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Router /simulators [get]
func GetSimulators(c *gin.Context) {
func getSimulators(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
return
}
db := common.GetDB()
var simulators []common.Simulator
err := db.Order("ID asc").Find(&simulators).Error
err = db.Order("ID asc").Find(&simulators).Error
if common.ProvideErrorResponse(c, err) {
return
}
@ -41,9 +51,9 @@ func GetSimulators(c *gin.Context) {
})
}
// AddSimulator godoc
// addSimulator godoc
// @Summary Add a simulator
// @ID AddSimulator
// @ID addSimulator
// @Accept json
// @Produce json
// @Tags simulators
@ -54,15 +64,35 @@ func GetSimulators(c *gin.Context) {
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Router /simulators [post]
func AddSimulator(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
func addSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Create)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
return
}
var newSimulator Simulator
err = c.BindJSON(&newSimulator)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
err = newSimulator.save()
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
}
}
// UpdateSimulator godoc
// updateSimulator godoc
// @Summary Update a simulator
// @ID UpdateSimulator
// @ID updateSimulator
// @Tags simulators
// @Accept json
// @Produce json
@ -74,15 +104,49 @@ func AddSimulator(c *gin.Context) {
// @Failure 500 "Internal server error"
// @Param simulatorID path int true "Simulator ID"
// @Router /simulators/{simulatorID} [put]
func UpdateSimulator(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
func updateSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Update)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
return
}
var modifiedSimulator Simulator
err = c.BindJSON(&modifiedSimulator)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
var s Simulator
err = s.ByID(uint(simulatorID))
if common.ProvideErrorResponse(c, err) {
return
}
err = s.update(modifiedSimulator)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
}
}
// GetSimulator godoc
// getSimulator godoc
// @Summary Get simulator
// @ID GetSimulator
// @ID getSimulator
// @Produce json
// @Tags simulators
// @Success 200 {object} common.SimulatorResponse "Simulator requested by user"
@ -92,15 +156,38 @@ func UpdateSimulator(c *gin.Context) {
// @Failure 500 "Internal server error"
// @Param simulatorID path int true "Simulator ID"
// @Router /simulators/{simulatorID} [get]
func GetSimulator(c *gin.Context) {
func getSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
return
}
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
var s Simulator
err = s.ByID(uint(simulatorID))
if common.ProvideErrorResponse(c, err) {
return
}
serializer := common.SimulatorSerializer{c, s.Simulator}
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
"simulator": serializer.Response(),
})
}
// DeleteSimulator godoc
// deleteSimulator godoc
// @Summary Delete a simulator
// @ID DeleteSimulator
// @ID deleteSimulator
// @Tags simulators
// @Produce json
// @Success 200 "OK."
@ -110,15 +197,90 @@ func GetSimulator(c *gin.Context) {
// @Failure 500 "Internal server error"
// @Param simulatorID path int true "Simulator ID"
// @Router /simulators/{simulatorID} [delete]
func DeleteSimulator(c *gin.Context) {
func deleteSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Delete)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
return
}
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
var s Simulator
err = s.ByID(uint(simulatorID))
if common.ProvideErrorResponse(c, err) {
return
}
err = s.delete()
if common.ProvideErrorResponse(c, err) {
return
}
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
"message": "OK.",
})
}
// SendActionToSimulator godoc
// getModelsOfSimulator godoc
// @Summary Get all simulation models in which the simulator is used
// @ID getModelsOfSimulator
// @Tags simulators
// @Produce json
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Param simulatorID path int true "Simulator ID"
// @Router /simulators/{simulatorID}/models [get]
func getModelsOfSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
return
}
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
var s Simulator
err = s.ByID(uint(simulatorID))
if common.ProvideErrorResponse(c, err) {
return
}
// get all associated simulation models
allModels, _, err := s.getModels()
if common.ProvideErrorResponse(c, err) {
return
}
serializer := common.SimulationModelsSerializer{c, allModels}
c.JSON(http.StatusOK, gin.H{
"models": serializer.Response(),
})
}
// sendActionToSimulator godoc
// @Summary Send an action to simulator
// @ID SendActionToSimulator
// @ID sendActionToSimulator
// @Tags simulators
// @Produce json
// @Param inputAction query string true "Action for simulator"
@ -129,7 +291,7 @@ func DeleteSimulator(c *gin.Context) {
// @Failure 500 "Internal server error"
// @Param simulatorID path int true "Simulator ID"
// @Router /simulators/{simulatorID}/action [post]
func SendActionToSimulator(c *gin.Context) {
func sendActionToSimulator(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})

View file

@ -24,3 +24,43 @@ func (s *Simulator) ByID(id uint) error {
}
return nil
}
func (s *Simulator) update(modifiedSimulator Simulator) error {
db := common.GetDB()
err := db.Model(s).Updates(map[string]interface{}{
"UUID": modifiedSimulator.UUID,
"Host": modifiedSimulator.Host,
"Modeltype": modifiedSimulator.Modeltype,
"Uptime": modifiedSimulator.Uptime,
"State": modifiedSimulator.State,
"StateUpdateAt": modifiedSimulator.StateUpdateAt,
"Properties": modifiedSimulator.Properties,
"RawProperties": modifiedSimulator.RawProperties,
}).Error
return err
}
func (s *Simulator) delete() error {
db := common.GetDB()
no_simulationmodels := db.Model(s).Association("SimulationModel").Count()
if no_simulationmodels > 0 {
return fmt.Errorf("Simulator cannot be deleted as it is still used in SimulationModels (active or dangling)")
}
// delete Simulator from DB (does NOT remain as dangling)
err := db.Delete(s).Error
return err
}
func (s *Simulator) getModels() ([]common.SimulationModel, int, error) {
db := common.GetDB()
var models []common.SimulationModel
err := db.Order("ID asc").Model(s).Related(&models, "SimulationModels").Error
return models, len(models), err
}

View file

@ -86,7 +86,7 @@ var msgVisupdated = common.ResponseMsgVisualization{
}
// Test /models endpoints
func TestSimulationModelEndpoints(t *testing.T) {
func TestVisualizationEndpoints(t *testing.T) {
db := common.DummyInitDB()
defer db.Close()

View file

@ -140,7 +140,7 @@ var msgWdgupdated = common.ResponseMsgWidget{
}
// Test /models endpoints
func TestSimulationModelEndpoints(t *testing.T) {
func TestWidgetEndpoints(t *testing.T) {
db := common.DummyInitDB()
defer db.Close()