Skip to content

Commit

Permalink
Refactor(cli) ApplyTemplate (#497)
Browse files Browse the repository at this point in the history
* refactor(cli) applytemplate

* fix(cli) tests

* fix(cli) simplified fbx template apply
  • Loading branch information
helderbetiol authored Jul 12, 2024
1 parent 209b63d commit 276764e
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 89 deletions.
80 changes: 2 additions & 78 deletions CLI/controllers/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package controllers

import (
"cli/models"
"cli/utils"
"errors"
"fmt"
"net/http"
Expand Down Expand Up @@ -79,83 +78,8 @@ func (controller Controller) ApplyTemplate(attr, data map[string]interface{}, en
return err
}

key := determineStrKey(tmpl, []string{"sizeWDHmm", "sizeWDHm"})

if sizeInf, hasSize := tmpl[key].([]any); hasSize && len(sizeInf) == 3 {
attr["size"] = sizeInf[:2]
attr["height"] = sizeInf[2]
utils.CopyMapVal(attr, tmpl, "shape")

if ent == models.DEVICE {
if tmpx, ok := tmpl["attributes"]; ok {
if x, ok := tmpx.(map[string]interface{}); ok {
if tmp, ok := x["type"]; ok {
if t, ok := tmp.(string); ok {
if t == "chassis" || t == "server" {
res := 0
if val, ok := sizeInf[2].(float64); ok {
res = int((val / 1000) / models.RACKUNIT)
} else if val, ok := sizeInf[2].(int); ok {
res = int((float64(val) / 1000) / models.RACKUNIT)
} else {
return errors.New("invalid size vector on given template")
}
attr["sizeU"] = res
}
}
}
}
}

} else if ent == models.ROOM {
//Copy additional Room specific attributes
utils.CopyMapVal(attr, tmpl, "technicalArea")
if _, ok := attr["technicalArea"]; ok {
attr["technical"] = attr["technicalArea"]
delete(attr, "technicalArea")
}

utils.CopyMapVal(attr, tmpl, "reservedArea")
if _, ok := attr["reservedArea"]; ok {
attr["reserved"] = attr["reservedArea"]
delete(attr, "reservedArea")
}

for _, attrName := range []string{"axisOrientation", "separators",
"pillars", "floorUnit", "tiles", "rows", "aisles",
"vertices", "colors", "tileAngle"} {
utils.CopyMapVal(attr, tmpl, attrName)
}

} else {
attr["sizeUnit"] = "mm"
attr["heightUnit"] = "mm"
}

//Copy Description
if _, ok := tmpl["description"]; ok {
data["description"] = tmpl["description"]
}

//fbxModel section
if check := utils.CopyMapVal(attr, tmpl, "fbxModel"); !check {
if ent != models.BLDG {
attr["fbxModel"] = ""
}
}

//Copy orientation if available
utils.CopyMapVal(attr, tmpl, "orientation")

//Merge attributes if available
if tmplAttrsInf, ok := tmpl["attributes"]; ok {
if tmplAttrs, ok := tmplAttrsInf.(map[string]interface{}); ok {
utils.MergeMaps(attr, tmplAttrs, false)
}
}
} else {
println("Warning, invalid size value in template.")
return errors.New("invalid size vector on given template")
if err := models.ApplyTemplateToObj(attr, data, tmpl, ent); err != nil {
return err
}

return nil
Expand Down
21 changes: 20 additions & 1 deletion CLI/controllers/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestApplyTemplateOfTypeDeviceError(t *testing.T) {
}
device["attributes"] = attributes
template := test_utils.GetEntity("deviceChasisTemplate", "device-template", "", "")
template["sizeWDHmm"] = []any{216, 659, "100"}
template["sizeWDHmm"] = []any{216, 659}

test_utils.MockGetObjTemplate(mockAPI, template)

Expand All @@ -74,6 +74,25 @@ func TestApplyTemplateOfTypeDeviceError(t *testing.T) {
assert.Equal(t, "invalid size vector on given template", err.Error())
}

func TestApplyTemplateOfTypeDeviceConvertError(t *testing.T) {
controller, mockAPI, _ := layersSetup(t)

device := test_utils.CopyMap(chassis)
attributes := map[string]any{
"template": "device-template",
}
device["attributes"] = attributes
template := test_utils.GetEntity("deviceChasisTemplate", "device-template", "", "")
template["sizeWDHmm"] = []any{216, 659, "100"}

test_utils.MockGetObjTemplate(mockAPI, template)

err := controller.ApplyTemplate(attributes, device, models.DEVICE)
assert.NotNil(t, err)

assert.Equal(t, "cannot convert string to float64", err.Error())
}

func TestApplyTemplateOfTypeRoomWorks(t *testing.T) {
controller, mockAPI, _ := layersSetup(t)

Expand Down
10 changes: 0 additions & 10 deletions CLI/controllers/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,3 @@ type ErrorWithInternalError struct {
func (err ErrorWithInternalError) Error() string {
return err.UserError.Error() + " caused by " + err.InternalError.Error()
}

// Utility functions
func determineStrKey(x map[string]interface{}, possible []string) string {
for idx := range possible {
if _, ok := x[possible[idx]]; ok {
return possible[idx]
}
}
return "" //The code should not reach this point!
}
54 changes: 54 additions & 0 deletions CLI/models/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package models

import (
l "cli/logger"
"cli/utils"
"errors"
"fmt"
"strconv"
"strings"
Expand Down Expand Up @@ -222,6 +224,58 @@ func SetRoomAreas(values []any) (map[string]any, error) {
}
}

func ApplyTemplateToObj(attr, data, tmpl map[string]any, ent int) error {
// Copy size
key := determineStrKey(tmpl, []string{"sizeWDHmm", "sizeWDHm"})
sizeInf, hasSize := tmpl[key].([]any)
if !hasSize || len(sizeInf) != 3 {
return errors.New("invalid size vector on given template")
}
attr["size"] = sizeInf[:2]
attr["height"] = sizeInf[2]
if ent == DEVICE {
if err := SetDeviceSizeUFromTemplate(attr, tmpl, sizeInf[2]); err != nil {
return err
}
} else if ent == ROOM {
ApplyRoomTemplateAttributes(attr, tmpl)
} else {
attr["sizeUnit"] = "mm"
attr["heightUnit"] = "mm"
}

// Copy description
if _, ok := tmpl["description"]; ok {
data["description"] = tmpl["description"]
}

// fbxModel section
if ent != BLDG && ent != ROOM {
utils.CopyMapVal(attr, tmpl, "fbxModel")
}

// Copy orientation and shape if available
utils.CopyMapVal(attr, tmpl, "orientation")
utils.CopyMapVal(attr, tmpl, "shape")

// Merge attributes if available
if tmplAttrs, ok := tmpl["attributes"].(map[string]any); ok {
utils.MergeMaps(attr, tmplAttrs, false)
}

return nil
}

// Helpers
func determineStrKey(x map[string]interface{}, possible []string) string {
for idx := range possible {
if _, ok := x[possible[idx]]; ok {
return possible[idx]
}
}
return "" //The code should not reach this point!
}

// errResponder helper func for specialUpdateNode
// used for separator, pillar err msgs and validateRoomAreas()
func ErrorResponder(attr, numElts string, multi bool) error {
Expand Down
14 changes: 14 additions & 0 deletions CLI/models/attributes_device.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,17 @@ func ComputeSizeUAndHeight(obj, data map[string]any) error {
}
return nil
}

func SetDeviceSizeUFromTemplate(deviceAttrs, tmpl map[string]any, tmplHeight any) error {
if tmplAttrs, ok := tmpl["attributes"].(map[string]any); ok {
if tmplType, ok := tmplAttrs["type"].(string); ok &&
(tmplType == "chassis" || tmplType == "server") {
if height, err := utils.GetFloat(tmplHeight); err != nil {
return err
} else {
deviceAttrs["sizeU"] = int((height / 1000) / RACKUNIT)
}
}
}
return nil
}
16 changes: 16 additions & 0 deletions CLI/models/attributes_device_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,19 @@ func TestComputeFromHeightFail(t *testing.T) {
}

// endregion

// region template

func TestSetDeviceSizeUFromTemplateWorks(t *testing.T) {
deviceAttrs := map[string]any{}
input := map[string]any{
"attributes": map[string]any{
"type": "chassis",
},
}
err := models.SetDeviceSizeUFromTemplate(deviceAttrs, input, any(10000))
assert.Nil(t, err)
assert.Equal(t, 224, deviceAttrs["sizeU"])
}

// endregion
21 changes: 21 additions & 0 deletions CLI/models/attributes_room.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,24 @@ func ValuesToSeparator(values []any) (string, Separator, error) {
}
return name, Separator{startPos, endPos, sepType}, nil
}

func ApplyRoomTemplateAttributes(attr, tmpl map[string]any) {
//Copy Room specific attributes
utils.CopyMapVal(attr, tmpl, "technicalArea")
if _, ok := attr["technicalArea"]; ok {
attr["technical"] = attr["technicalArea"]
delete(attr, "technicalArea")
}

utils.CopyMapVal(attr, tmpl, "reservedArea")
if _, ok := attr["reservedArea"]; ok {
attr["reserved"] = attr["reservedArea"]
delete(attr, "reservedArea")
}

for _, attrName := range []string{"axisOrientation", "separators",
"pillars", "floorUnit", "tiles", "rows", "aisles",
"vertices", "colors", "tileAngle"} {
utils.CopyMapVal(attr, tmpl, attrName)
}
}

0 comments on commit 276764e

Please sign in to comment.