mirror of
https://git.rwth-aachen.de/acs/public/villas/web-backend-go/
synced 2025-03-30 00:00:12 +01:00
add test for scenario duplication
This commit is contained in:
parent
7a540db693
commit
780334592f
2 changed files with 193 additions and 76 deletions
|
@ -25,10 +25,11 @@ package user
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func duplicateScenarioForUser(s database.Scenario, user *database.User) <-chan error {
|
func duplicateScenarioForUser(s database.Scenario, user *database.User) <-chan error {
|
||||||
|
@ -397,6 +398,59 @@ func duplicateWidget(w database.Widget, dashboardID uint, signalMap map[uint]uin
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Container struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Image string `json:"image"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TemplateSpec struct {
|
||||||
|
Containers []Container `json:"containers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JobTemplate struct {
|
||||||
|
Spec TemplateSpec `json:"spec"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JobSpec struct {
|
||||||
|
Active string `json:"activeDeadlineSeconds"`
|
||||||
|
Template JobTemplate `json:"template"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JobMetaData struct {
|
||||||
|
JobName string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type KubernetesJob struct {
|
||||||
|
Spec JobSpec `json:"spec"`
|
||||||
|
MetaData JobMetaData `json:"metadata"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ICPropertiesKubernetesJob struct {
|
||||||
|
Job KubernetesJob `json:"job"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Owner string `json:"owner"`
|
||||||
|
Category string `json:"category"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ICStatus struct {
|
||||||
|
State string `json:"state"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Uptime float64 `json:"uptime"`
|
||||||
|
Result string `json:"result"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
ManagedBy string `json:"managed_by"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ICUpdateKubernetesJob struct {
|
||||||
|
Properties ICPropertiesKubernetesJob `json:"properties"`
|
||||||
|
Status ICStatus `json:"status"`
|
||||||
|
Schema json.RawMessage `json:"schema"`
|
||||||
|
}
|
||||||
|
|
||||||
func duplicateIC(ic database.InfrastructureComponent, userName string) (string, error) {
|
func duplicateIC(ic database.InfrastructureComponent, userName string) (string, error) {
|
||||||
|
|
||||||
//WARNING: this function only works with the kubernetes-simple manager of VILLAScontroller
|
//WARNING: this function only works with the kubernetes-simple manager of VILLAScontroller
|
||||||
|
@ -405,54 +459,8 @@ func duplicateIC(ic database.InfrastructureComponent, userName string) (string,
|
||||||
}
|
}
|
||||||
|
|
||||||
newUUID := uuid.New().String()
|
newUUID := uuid.New().String()
|
||||||
log.Printf("New IC UUID: %s", newUUID)
|
|
||||||
|
|
||||||
type Container struct {
|
var lastUpdate ICUpdateKubernetesJob
|
||||||
Name string `json:"name"`
|
|
||||||
Image string `json:"image"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TemplateSpec struct {
|
|
||||||
Containers []Container `json:"containers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type JobTemplate struct {
|
|
||||||
Spec TemplateSpec `json:"spec"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type JobSpec struct {
|
|
||||||
Active string `json:"activeDeadlineSeconds"`
|
|
||||||
Template JobTemplate `json:"template"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type JobMetaData struct {
|
|
||||||
JobName string `json:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type KubernetesJob struct {
|
|
||||||
Spec JobSpec `json:"spec"`
|
|
||||||
MetaData JobMetaData `json:"metadata"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ICPropertiesToCopy struct {
|
|
||||||
Job KubernetesJob `json:"job"`
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Location string `json:"location"`
|
|
||||||
Owner string `json:"owner"`
|
|
||||||
Category string `json:"category"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ICUpdateToCopy struct {
|
|
||||||
Properties ICPropertiesToCopy `json:"properties"`
|
|
||||||
Status json.RawMessage `json:"status"`
|
|
||||||
Schema json.RawMessage `json:"schema"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastUpdate ICUpdateToCopy
|
|
||||||
log.Println(ic.StatusUpdateRaw.RawMessage)
|
|
||||||
err := json.Unmarshal(ic.StatusUpdateRaw.RawMessage, &lastUpdate)
|
err := json.Unmarshal(ic.StatusUpdateRaw.RawMessage, &lastUpdate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newUUID, err
|
return newUUID, err
|
||||||
|
|
|
@ -46,6 +46,7 @@ import (
|
||||||
|
|
||||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/configuration"
|
"git.rwth-aachen.de/acs/public/villas/web-backend-go/configuration"
|
||||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||||
|
component_configuration "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration"
|
||||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/dashboard"
|
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/dashboard"
|
||||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/file"
|
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/file"
|
||||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||||
|
@ -83,6 +84,7 @@ func TestMain(m *testing.M) {
|
||||||
|
|
||||||
scenario.RegisterScenarioEndpoints(api.Group("/scenarios"))
|
scenario.RegisterScenarioEndpoints(api.Group("/scenarios"))
|
||||||
infrastructure_component.RegisterICEndpoints(api.Group("/ic"))
|
infrastructure_component.RegisterICEndpoints(api.Group("/ic"))
|
||||||
|
component_configuration.RegisterComponentConfigurationEndpoints(api.Group("/configs"))
|
||||||
dashboard.RegisterDashboardEndpoints(api.Group("/dashboards"))
|
dashboard.RegisterDashboardEndpoints(api.Group("/dashboards"))
|
||||||
file.RegisterFileEndpoints(api.Group("/files"))
|
file.RegisterFileEndpoints(api.Group("/files"))
|
||||||
widget.RegisterWidgetEndpoints(api.Group("/widgets"))
|
widget.RegisterWidgetEndpoints(api.Group("/widgets"))
|
||||||
|
@ -861,8 +863,7 @@ func TestDuplicateScenarioForUser(t *testing.T) {
|
||||||
|
|
||||||
// AMQP Connection startup is tested here
|
// AMQP Connection startup is tested here
|
||||||
// Not repeated in other tests because it is only needed once
|
// Not repeated in other tests because it is only needed once
|
||||||
//session = helper.NewAMQPSession("villas-test-session", amqpURI, "villas", infrastructure_component.ProcessMessage)
|
session = helper.NewAMQPSession("villas-test-session", amqpURI, "villas", infrastructure_component.ProcessMessage)
|
||||||
//SetAMQPSession(session)
|
|
||||||
|
|
||||||
// authenticate as admin (needed to create original IC)
|
// authenticate as admin (needed to create original IC)
|
||||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||||
|
@ -881,13 +882,17 @@ func TestDuplicateScenarioForUser(t *testing.T) {
|
||||||
assert.NotEqual(t, 99, fileID)
|
assert.NotEqual(t, 99, fileID)
|
||||||
|
|
||||||
// add IC
|
// add IC
|
||||||
err = addIC(amqpURI, token)
|
err = addIC(session, token)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// wait for IC to be created asynchronously
|
// wait for IC to be created asynchronously
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(4 * time.Second)
|
||||||
|
|
||||||
// add component config
|
// add component config
|
||||||
|
err = addComponentConfig(scenarioID, token)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// TODO: add signals
|
||||||
|
|
||||||
// add dashboards to scenario
|
// add dashboards to scenario
|
||||||
err = addTwoDashboards(scenarioID, token)
|
err = addTwoDashboards(scenarioID, token)
|
||||||
|
@ -907,6 +912,11 @@ func TestDuplicateScenarioForUser(t *testing.T) {
|
||||||
myUser, err := NewUser(username, "", "schnitti@lauch.de", "User", true)
|
myUser, err := NewUser(username, "", "schnitti@lauch.de", "User", true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// create fake IC duplicate (would normally be created by villas-controller)
|
||||||
|
err = addFakeIC(session, token)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
SetAMQPSession(session)
|
||||||
if err := <-duplicateScenarioForUser(originalSo, &myUser.User); err != nil {
|
if err := <-duplicateScenarioForUser(originalSo, &myUser.User); err != nil {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
@ -918,20 +928,6 @@ func TestDuplicateScenarioForUser(t *testing.T) {
|
||||||
assert.Equal(t, 1, len(dplScenarios))
|
assert.Equal(t, 1, len(dplScenarios))
|
||||||
assert.Equal(t, originalSo.StartParameters, dplScenarios[0].StartParameters)
|
assert.Equal(t, originalSo.StartParameters, dplScenarios[0].StartParameters)
|
||||||
|
|
||||||
// compare original and duplicated dashboards
|
|
||||||
err = db.Order("created_at asc").Find(&dashboards).Error
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, 4, len(dashboards))
|
|
||||||
assert.Equal(t, dashboards[0].Name, dashboards[2].Name)
|
|
||||||
assert.Equal(t, dashboards[0].Grid, dashboards[2].Grid)
|
|
||||||
assert.Equal(t, dashboards[0].Height, dashboards[2].Height)
|
|
||||||
assert.NotEqual(t, dashboards[0].ScenarioID, dashboards[2].ScenarioID)
|
|
||||||
|
|
||||||
assert.Equal(t, dashboards[1].Name, dashboards[3].Name)
|
|
||||||
assert.Equal(t, dashboards[1].Grid, dashboards[3].Grid)
|
|
||||||
assert.Equal(t, dashboards[1].Height, dashboards[3].Height)
|
|
||||||
assert.NotEqual(t, dashboards[1].ScenarioID, dashboards[3].ScenarioID)
|
|
||||||
|
|
||||||
// compare original and duplicated file
|
// compare original and duplicated file
|
||||||
var files []database.File
|
var files []database.File
|
||||||
err = db.Find(&files).Error
|
err = db.Find(&files).Error
|
||||||
|
@ -943,6 +939,52 @@ func TestDuplicateScenarioForUser(t *testing.T) {
|
||||||
assert.Equal(t, files[0].ImageWidth, files[1].ImageWidth)
|
assert.Equal(t, files[0].ImageWidth, files[1].ImageWidth)
|
||||||
assert.Equal(t, files[0].Size, files[1].Size)
|
assert.Equal(t, files[0].Size, files[1].Size)
|
||||||
assert.NotEqual(t, files[0].ScenarioID, files[1].ScenarioID)
|
assert.NotEqual(t, files[0].ScenarioID, files[1].ScenarioID)
|
||||||
|
assert.NotEqual(t, files[0].ID, files[1].ID)
|
||||||
|
|
||||||
|
// compare original and duplicated component config
|
||||||
|
var configs []database.ComponentConfiguration
|
||||||
|
err = db.Find(&configs).Error
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 2, len(configs))
|
||||||
|
assert.Equal(t, configs[0].Name, configs[1].Name)
|
||||||
|
assert.Equal(t, configs[0].FileIDs, configs[1].FileIDs)
|
||||||
|
assert.Equal(t, configs[0].InputMapping, configs[1].InputMapping)
|
||||||
|
assert.Equal(t, configs[0].OutputMapping, configs[1].OutputMapping)
|
||||||
|
assert.Equal(t, configs[0].StartParameters, configs[1].StartParameters)
|
||||||
|
assert.NotEqual(t, configs[0].ScenarioID, configs[1].ScenarioID)
|
||||||
|
assert.NotEqual(t, configs[0].ICID, configs[1].ICID)
|
||||||
|
assert.NotEqual(t, configs[0].ID, configs[1].ID)
|
||||||
|
|
||||||
|
// compare original and duplicated infrastructure component
|
||||||
|
|
||||||
|
// compare original and duplicated dashboards
|
||||||
|
err = db.Order("created_at asc").Find(&dashboards).Error
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 4, len(dashboards))
|
||||||
|
assert.Equal(t, dashboards[0].Name, dashboards[2].Name)
|
||||||
|
assert.Equal(t, dashboards[0].Grid, dashboards[2].Grid)
|
||||||
|
assert.Equal(t, dashboards[0].Height, dashboards[2].Height)
|
||||||
|
assert.NotEqual(t, dashboards[0].ScenarioID, dashboards[2].ScenarioID)
|
||||||
|
assert.NotEqual(t, dashboards[0].ID, dashboards[2].ID)
|
||||||
|
|
||||||
|
assert.Equal(t, dashboards[1].Name, dashboards[3].Name)
|
||||||
|
assert.Equal(t, dashboards[1].Grid, dashboards[3].Grid)
|
||||||
|
assert.Equal(t, dashboards[1].Height, dashboards[3].Height)
|
||||||
|
assert.NotEqual(t, dashboards[1].ScenarioID, dashboards[3].ScenarioID)
|
||||||
|
assert.NotEqual(t, dashboards[1].ID, dashboards[3].ID)
|
||||||
|
|
||||||
|
// compare original and duplicated widget
|
||||||
|
var widgets []database.Widget
|
||||||
|
err = db.Find(&widgets).Error
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 2, len(widgets))
|
||||||
|
assert.Equal(t, widgets[0].Name, widgets[1].Name)
|
||||||
|
assert.Equal(t, widgets[0].CustomProperties, widgets[1].CustomProperties)
|
||||||
|
assert.Equal(t, widgets[0].SignalIDs, widgets[1].SignalIDs)
|
||||||
|
assert.Equal(t, widgets[0].MinHeight, widgets[1].MinHeight)
|
||||||
|
assert.Equal(t, widgets[0].MinWidth, widgets[1].MinWidth)
|
||||||
|
assert.NotEqual(t, widgets[0].DashboardID, widgets[1].DashboardID)
|
||||||
|
assert.NotEqual(t, widgets[0].ID, widgets[1].ID)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1019,7 +1061,6 @@ func addFile(scenarioID uint, token string) (uint, error) {
|
||||||
router.ServeHTTP(w, req)
|
router.ServeHTTP(w, req)
|
||||||
|
|
||||||
newFileID, err := helper.GetResponseID(w.Body)
|
newFileID, err := helper.GetResponseID(w.Body)
|
||||||
log.Println(w.Body)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 99, err
|
return 99, err
|
||||||
}
|
}
|
||||||
|
@ -1121,7 +1162,7 @@ func newTrue() *bool {
|
||||||
return &b
|
return &b
|
||||||
}
|
}
|
||||||
|
|
||||||
func addIC(amqpURI string, token string) error {
|
func addIC(session *helper.AMQPsession, token string) error {
|
||||||
// create IC
|
// create IC
|
||||||
var newIC = ICRequest{
|
var newIC = ICRequest{
|
||||||
UUID: "7be0322d-354e-431e-84bd-ae4c9633138b",
|
UUID: "7be0322d-354e-431e-84bd-ae4c9633138b",
|
||||||
|
@ -1140,31 +1181,99 @@ func addIC(amqpURI string, token string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fake an IC update (create) message
|
// fake an IC update (create) message
|
||||||
var update infrastructure_component.ICUpdate
|
var update ICUpdateKubernetesJob
|
||||||
update.Status.State = "idle"
|
|
||||||
update.Status.ManagedBy = newIC.Manager
|
|
||||||
update.Properties.Name = newIC.Name
|
update.Properties.Name = newIC.Name
|
||||||
update.Properties.Category = newIC.Category
|
update.Properties.Category = newIC.Category
|
||||||
update.Properties.Type = newIC.Type
|
update.Properties.Type = newIC.Type
|
||||||
update.Properties.UUID = newIC.UUID
|
update.Properties.UUID = newIC.UUID
|
||||||
|
update.Properties.Job.MetaData.JobName = "myJob"
|
||||||
|
update.Properties.Job.Spec.Active = "70"
|
||||||
|
update.Status.ManagedBy = newIC.Manager
|
||||||
|
update.Status.State = newIC.State
|
||||||
|
var container Container
|
||||||
|
container.Name = "myContainer"
|
||||||
|
container.Image = "python:latest"
|
||||||
|
var Containers []Container
|
||||||
|
update.Properties.Job.Spec.Template.Spec.Containers = append(Containers, container)
|
||||||
|
|
||||||
payload, err := json.Marshal(update)
|
payload, err := json.Marshal(update)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//var headers map[string]interface{}
|
//session = helper.NewAMQPSession("villas-test-session", amqpURI, "villas", infrastructure_component.ProcessMessage)
|
||||||
//headers = make(map[string]interface{}) // empty map
|
|
||||||
//headers["uuid"] = newIC2.Manager // set uuid
|
|
||||||
session = helper.NewAMQPSession("villas-test-session", amqpURI, "villas", infrastructure_component.ProcessMessage)
|
|
||||||
SetAMQPSession(session)
|
SetAMQPSession(session)
|
||||||
|
|
||||||
|
//time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
err = session.CheckConnection()
|
err = session.CheckConnection()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = session.Send(payload, newIC.Manager)
|
err = session.Send(payload, newIC.Manager)
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func addComponentConfig(scenarioID uint, token string) error {
|
||||||
|
type ConfigRequest struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
ScenarioID uint `json:"scenarioID,omitempty"`
|
||||||
|
ICID uint `json:"icID,omitempty"`
|
||||||
|
StartParameters postgres.Jsonb `json:"startParameters,omitempty"`
|
||||||
|
FileIDs []int64 `json:"fileIDs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var newConfig1 = ConfigRequest{
|
||||||
|
Name: "Example for Signal generator",
|
||||||
|
ScenarioID: scenarioID,
|
||||||
|
ICID: 1,
|
||||||
|
StartParameters: postgres.Jsonb{RawMessage: json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)},
|
||||||
|
FileIDs: []int64{},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err := helper.TestEndpoint(router, token,
|
||||||
|
"/api/v2/configs", "POST", helper.KeyModels{"config": newConfig1})
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addFakeIC(session *helper.AMQPsession, token string) error {
|
||||||
|
|
||||||
|
db := database.GetDB()
|
||||||
|
var originalIC database.InfrastructureComponent
|
||||||
|
err := db.Find(&originalIC, 1).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//session = helper.NewAMQPSession("villas-test-session", amqpURI, "villas", infrastructure_component.ProcessMessage)
|
||||||
|
log.Println(session)
|
||||||
|
SetAMQPSession(session)
|
||||||
|
|
||||||
|
//time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
|
err = session.CheckConnection()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var update ICUpdateKubernetesJob
|
||||||
|
err = json.Unmarshal(originalIC.StatusUpdateRaw.RawMessage, &update)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
update.Properties.UUID = "4854af30-325f-44a5-ad59-b67b2597de68"
|
||||||
|
|
||||||
|
payload, err := json.Marshal(update)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println(session)
|
||||||
|
|
||||||
|
err = session.Send(payload, originalIC.Manager)
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue