Skip to content
Snippets Groups Projects
Commit ff18ed79 authored by Malte Bauch's avatar Malte Bauch
Browse files

json unmarshal for nodes, connections and links

added function for preformatting

sadly the json we get from ciena for node-edge-point doesnt fit to anything
from ygot.
parent 56143f36
No related branches found
No related tags found
3 merge requests!90Develop,!74Resolve "Unmarshal JSON with ygot",!53V.0.1.0 Codename Threadbare
Pipeline #55230 passed
[[client]]
identifier = "ciena-mcp"
endpoint = "172.17.0.3:8080"
gjsonDefaultPath = "data.#.object_data.tapi-object-data"
gjsonConnectionsPath = "data.#.object_data"
......@@ -14,6 +14,7 @@ require (
github.com/onsi/ginkgo v1.13.0 // indirect
github.com/openconfig/ygot v0.8.7
github.com/rivo/tview v0.0.0-20201018122409-d551c850a743
github.com/tidwall/gjson v1.6.3
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
google.golang.org/grpc v1.29.1
google.golang.org/protobuf v1.23.0
......
......@@ -3,8 +3,10 @@ package interfaces
// ClientConfig contains SBI client
// configuration parameters
type ClientConfig struct {
Identifier string `toml:"identifier"`
Endpoint string `toml:"endpoint"`
Username string `toml:"username"`
Password string `toml:"password"`
Identifier string `toml:"identifier"`
Endpoint string `toml:"endpoint"`
Username string `toml:"username"`
Password string `toml:"password"`
GjsonDefaultPath string `toml:"gjsonDefaultPath"`
GjsonConnectionsPath string `toml:"gjsonConnectionsPath"`
}
......@@ -9,11 +9,14 @@ import (
apiclient "code.fbi.h-da.de/cocsn/swagger/apis/mcp/client"
"code.fbi.h-da.de/cocsn/yang-modules/generated/tapi"
"crypto/tls"
"encoding/json"
"github.com/go-openapi/runtime"
httptransport "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"github.com/openconfig/ygot/ygot"
"github.com/tidwall/gjson"
"net/http"
"strings"
)
//MCPClient handles requests to a Ciena MCP RESTCONF endpoint
......@@ -61,11 +64,25 @@ func NewMCPClient(endpoint, username, password string, database *database.Databa
func (c *MCPClient) GetConnections() error {
defer c.buffer.Reset()
_, err := c.client.TapiConnectivityCore.GetTapiCoreContextConnection(nil)
if err != nil { return err}
dest := &tapi.TapiCommon_Context_ConnectivityContext_Connection{}
if err := tapi.Unmarshal(c.buffer.Bytes(), dest); err != nil { return err }
c.database.StoreConnections(c.buffer.String())
log.Debug(c.buffer.Next(25))
if err != nil {
return err
}
json := preformatJSON(c.buffer.String(), c.config.GjsonConnectionsPath)
for _, jsonEntry := range json.Array() {
dest := &tapi.TapiCommon_Context_ConnectivityContext_Connection{}
if err := tapi.Unmarshal([]byte(jsonEntry.String()), dest); err != nil {
//TODO: think about a way how to handle this.
//logging every error is kinda ugly, since ciena tapi throws a
//lot of them.
log.Info(err)
}
log.Info(*dest.Uuid)
}
// c.database.StoreConnections(c.buffer.String())
// log.Debug(c.buffer.Next(25))
return err
}
......@@ -74,11 +91,25 @@ func (c *MCPClient) GetConnections() error {
func (c *MCPClient) GetLinks() error {
defer c.buffer.Reset()
_, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyLink(nil)
if err != nil { return err}
dest := &tapi.TapiCommon_Context_TopologyContext_Topology_Link{}
if err := tapi.Unmarshal(c.buffer.Bytes(), dest); err != nil { return err }
c.database.StoreLinks(c.buffer.String())
log.Debug(c.buffer.Next(25))
if err != nil {
return err
}
json := preformatJSON(c.buffer.String(), c.config.GjsonDefaultPath)
for _, jsonEntry := range json.Array() {
dest := &tapi.TapiCommon_Context_TopologyContext_Topology_Link{}
if err := tapi.Unmarshal([]byte(jsonEntry.String()), dest); err != nil {
//TODO: think about a way how to handle this.
//logging every error is kinda ugly, since ciena tapi throws a
//lot of them.
log.Info(err)
}
log.Info(*dest.Uuid)
}
// c.database.StoreLinks(c.buffer.String())
// log.Debug(c.buffer.Next(25))
return err
}
......@@ -87,11 +118,25 @@ func (c *MCPClient) GetLinks() error {
func (c *MCPClient) GetNodes() error {
defer c.buffer.Reset()
_, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNode(nil)
if err != nil { return err}
dest := &tapi.TapiCommon_Context_TopologyContext_Topology_Node{}
if err := tapi.Unmarshal(c.buffer.Bytes(), dest); err != nil { return err }
c.database.StoreNodes(c.buffer.String())
log.Debug(c.buffer.Next(25))
if err != nil {
return err
}
json := preformatJSON(c.buffer.String(), c.config.GjsonDefaultPath)
for _, jsonEntry := range json.Array() {
dest := &tapi.TapiCommon_Context_TopologyContext_Topology_Node{}
if err := tapi.Unmarshal([]byte(jsonEntry.String()), dest); err != nil {
//TODO: think about a way how to handle this.
//logging every error is kinda ugly, since ciena tapi throws a
//lot of them.
log.Info(err)
}
log.Info(*dest.Uuid)
}
// c.database.StoreNodes(c.buffer.String())
// log.Debug(c.buffer.Next(25))
return err
}
......@@ -100,10 +145,75 @@ func (c *MCPClient) GetNodes() error {
func (c *MCPClient) GetNodeEdgePoints() error {
defer c.buffer.Reset()
_, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNodeEdgePoint(nil)
if err != nil { return err}
if err != nil {
return err
}
//TODO: there is no tapi ygot struct that fits the ciena node-edge-point
dest := &tapi.TapiCommon_Context_TopologyContext_Topology_Link_NodeEdgePoint{}
if err := tapi.Unmarshal(c.buffer.Bytes(), dest); err != nil { return err }
if err := tapi.Unmarshal(c.buffer.Bytes(), dest); err != nil {
return err
}
c.database.StoreNodeEdgePoints(c.buffer.String())
log.Debug(c.buffer.Next(25))
return err
}
\ No newline at end of file
}
//preformatJSON preformats the recieved JSON for further processing
func preformatJSON(jsn string, path string) *gjson.Result {
//TODO: move this!
modifierName := "uppercase"
gjson.AddModifier(modifierName, func(jsonString, arg string) string {
var jsonMap interface{}
err := json.Unmarshal([]byte(jsonString), &jsonMap)
if err != nil {
log.Info("failed unmarshal for JSON")
}
jsonMap = uppercaseJSONValues(jsonMap)
result, err := json.Marshal(jsonMap)
if err != nil {
log.Info("failed marshal for JSON")
}
return string(result)
})
formattedJSON := gjson.Get(jsn, path+"|@"+modifierName)
return &formattedJSON
}
//uppercaseJSONValues takes a interface{} created with json.Unmarshal() and changes the containing
//string values to uppercase
//returns a interface{} which can be changed back into a JSON string via
//json.Marshal()
func uppercaseJSONValues(jsonMap interface{}) interface{} {
switch jsonMap := jsonMap.(type) {
//check if []interface{} and go through every entry recursively
case []interface{}:
for i := range jsonMap {
jsonMap[i] = uppercaseJSONValues(jsonMap[i])
}
return jsonMap
//check if map[string]interface, handle ciena tapi json specific fixes
//and go on recursively
case map[string]interface{}:
tmpInterfaceMap := make(map[string]interface{}, len(jsonMap))
for k, v := range jsonMap {
//TODO: maybe we can uppercase them too, but for now:
//DO NOT uppercase uuid's
if strings.Contains(k, "uuid") {
tmpInterfaceMap[k] = v
} else {
tmpInterfaceMap[k] = uppercaseJSONValues(v)
}
}
return tmpInterfaceMap
//ygot: requires enums in uppercase and since CIENA TAPI does sometimes
//provide faulty JSON values we need to uppercase them before we process
//them further
case string:
return strings.ToUpper(jsonMap)
//default: do nothing (like for bool or other stuff)
default:
return jsonMap
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment