Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial skeleton for Tr1d1um (WIP) #1

Merged
merged 10 commits into from
Sep 15, 2017
111 changes: 111 additions & 0 deletions src/glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion src/glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@ homepage: https://github.com/Comcast/tr1d1um
import:
- package: github.com/Comcast/webpa-common
version: cb246362b61aaf042a936fa615a48554d111f9b4

40 changes: 40 additions & 0 deletions src/tr1d1um/WDMP_Type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package main

const(
COMMAND_GET = "GET"
COMMAND_GET_ATTRS = "GET_ATTRIBUTES"
COMMAND_SET = "SET"
COMMAND_SET_ATTRS = "SET_ATTRIBUTES"
COMMAND_TEST_SET = "TEST_AND_SET"

HEADER_WPA_SYNC_OLD_CID = "X-Webpa-Sync-Old-Cid"
HEADER_WPA_SYNC_NEW_CID = "X-Webpa-Sync-New-Cid"
HEADER_WPA_SYNC_CMC = "X-Webpa-Sync-Cmc"

ERR_UNSUCCESSFUL_DATA_PARSE = "Unsuccessful Data Parse"
ERR_UNSUCCESSFUL_DATA_WRAP = "Unsuccessful WDMP data transfer into wrp message"

)

type GetWDMP struct {
Command string `json:"command"`
Names []string `json:"names,omitempty"`
Attribute string `json:"attributes,omitempty"`
}

type SetParam struct {
Name* string `json:"name"`
DataType* int32 `json:"dataType,omitempty"`
Value interface{} `json:"value,omitempty"`
Attributes Attr `json:"attributes,omitempty"`
}

type SetWDMP struct {
Command string `json:"command"`
OldCid string `json:"old-cid,omitempty"`
NewCid string `json:"new-cid,omitempty"`
SyncCmc string `json:"sync-cmc,omitempty"`
Parameters []SetParam `json:"parameters,omitempty"`
}

type Attr map[string]interface{}
138 changes: 138 additions & 0 deletions src/tr1d1um/helper_functions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package main

import (
"github.com/Comcast/webpa-common/wrp"
"encoding/json"
"strings"
"net/http"
"io"
"errors"
)

var (
ErrJsonEmpty = errors.New("JSON payload is empty")
)

//Given some wdmp data, wraps it into a wrp object, returns the resulting payload
func WrapInWrp(wdmpData []byte) (payload []byte, err error){
wrpMessage := wrp.Message{Type:wrp.SimpleRequestResponseMessageType, Payload:wdmpData}
payload, err = json.Marshal(wrpMessage)
return
}

// All we care about is the payload. Method helps abstract away work done with the WDMP object
func GetFlavorFormat(req *http.Request, attr, formValKey, sep string) (payload[]byte, err error){
wdmp := new(GetWDMP)

if names := strings.Split(req.FormValue(formValKey),sep); len(names) > 0 {
wdmp.Command = COMMAND_GET
wdmp.Names = names
} else{
err = errors.New("names is a required property for GET")
return
}

if attributes := req.FormValue(attr); attributes != "" {
wdmp.Command = COMMAND_GET_ATTRS
}

payload, err = json.Marshal(wdmp)
return
}

func SetFlavorFormat(req *http.Request, ReadEntireBody func(io.Reader)(payload []byte, err error)) (payload[]byte, err error){
wdmp := new(SetWDMP)
DecodeJsonPayload(req, wdmp, ReadEntireBody)

wdmp.Command, err = ValidateAndGetCommand(req, wdmp)

if err != nil {
return
}

payload, err = json.Marshal(wdmp)
return
}

func ValidateAndGetCommand(req *http.Request, wdmp *SetWDMP) (command string, err error){
if newCid := req.Header.Get(HEADER_WPA_SYNC_NEW_CID); newCid != "" {
wdmp.OldCid = req.Header.Get(HEADER_WPA_SYNC_OLD_CID)
wdmp.NewCid = newCid
wdmp.SyncCmc = req.Header.Get(HEADER_WPA_SYNC_CMC)
command, err = validateSETParams(false, wdmp, COMMAND_TEST_SET)
} else {
command, err = validateSETParams(true, wdmp, "")
}
return
}


/* -Inputs-:
**checkingForSetAttr**: true if we're checking for the required parameter properties for the SET_ATTRIBUTES command
These properties are: attributes and name

**wdmp**: the WDMP object from which we retrieve the parameters

**override**: overrides the final suggested command if non-empty. Useful if one just wants to check for SET command
parameter properties (value, dataType, name)

-Outputs-:
**command**: the final command based on the analysis of the parameters
**err**: it is non-nil if any required property is violated
*/
func validateSETParams(checkingForSetAttr bool, wdmp *SetWDMP, override string) (command string, err error){
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this method having in mind this description: "If you provide both value and attributes by default it will do set values" from swagger
If this description referred to the logic that applies on the device side and not in TR1D1UM, then this was a misunderstanding. @schmidtw

for _, sp := range wdmp.Parameters {
if sp.Name == nil {
err = errors.New("name is required for parameters")
return
}

if checkingForSetAttr {
if sp.Value != nil || sp.Attributes == nil {
checkingForSetAttr = false
}
} else { //in this case, we are just checking valid parameters for SET
if sp.DataType == nil || sp.Value == nil {
err = errors.New("dataType and value are required for SET command")
}
}
}

if override != "" {
command = override
return
}

if checkingForSetAttr { // checked for SET_ATTRS properties until the end and found no violation
command = COMMAND_SET_ATTRS
return
}

command = COMMAND_SET
return
}

func DecodeJsonPayload(req *http.Request, v interface{}, ReadEntireBody func(io.Reader)([]byte, error)) (err error) {
if ReadEntireBody == nil {
err = errors.New("method ReadEntireBody is undefined")
return
}
payload, err := ReadEntireBody(req.Body)
req.Body.Close()

if err != nil {
return
}

if len(payload) == 0 {
err = ErrJsonEmpty
return
}

err = json.Unmarshal(payload, v)
if err != nil {
return
}
return
}

41 changes: 41 additions & 0 deletions src/tr1d1um/helper_functions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"testing"
"encoding/json"
"github.com/Comcast/webpa-common/wrp"
"github.com/stretchr/testify/assert"
"net/http"
)

//Some tests are trivial but worth having
func TestWrapInWrp(t *testing.T) {
assert := assert.New(t)
input := []byte("data")
wrpMsg := wrp.Message{Type:wrp.SimpleRequestResponseMessageType, Payload:input}
expected, expectedErr := json.Marshal(wrpMsg)

actual, actualErr := WrapInWrp(input)
assert.EqualValues(expected, actual)
assert.EqualValues(expectedErr, actualErr)
}

func TestGetFormattedData(t *testing.T) {
assert := assert.New(t)
req, err := http.NewRequest("GET", "api/device/config?names=param1,param2,param3", nil)

if err != nil {
assert.FailNow("Could not make new request")
}

wdmp := &GetWDMP{Command:COMMAND_GET}
wdmp.Names = []string{"param1","param2","param3"}

expected, expectedErr := json.Marshal(wdmp)

actual, actualErr := GetFlavorFormat(req,"attributes", "names", ",")

assert.EqualValues(expected, actual)
assert.EqualValues(expectedErr, actualErr)

}
Loading