diff --git a/pkg/datastore/target/gnmi.go b/pkg/datastore/target/gnmi.go index 9a90d984..4be21331 100644 --- a/pkg/datastore/target/gnmi.go +++ b/pkg/datastore/target/gnmi.go @@ -158,6 +158,8 @@ func (t *gnmiTarget) Get(ctx context.Context, req *sdcpb.GetDataRequest) (*sdcpb return schemaRsp, nil } +var nsMap = make(map[string]string) + func (t *gnmiTarget) Set(ctx context.Context, source TargetSource) (*sdcpb.SetDataResponse, error) { var upds []*sdcpb.Update var deletes []*sdcpb.Path @@ -193,11 +195,91 @@ func (t *gnmiTarget) Set(ctx context.Context, source TargetSource) (*sdcpb.SetDa return nil, err } if jsonData != nil { - jsonBytes, err := json.Marshal(jsonData) - if err != nil { - return nil, err + upds = []*sdcpb.Update{} + for key, value := range jsonData.(map[string]any) { + keyParts := strings.Split(key, ":") + rootNamespace := "" + rootNodeName := "" + if len(keyParts) == 2 { + rootNamespace = keyParts[0] + rootNodeName = keyParts[1] + } + + updsPerNs := make(map[string]map[string]any) + + // check second level of data to distinguish namespaces + for k, v := range value.(map[string]any) { + kP := strings.Split(k, ":") + var leafNamespace string + var leafNodeName string + if len(kP) == 2 { + leafNodeName = kP[1] + if len(kP) == 2 && kP[0] != rootNamespace { + // diverged namespace + leafNamespace = kP[0] + nsMap[rootNodeName+"/"+leafNodeName] = rootNamespace + } else { + // root namespace + leafNamespace = rootNamespace + } + } else { + leafNodeName = kP[0] + leafNamespace = rootNamespace + nsMap[rootNodeName] = rootNamespace + } + _, found := updsPerNs[leafNamespace] + if !found { + updsPerNs[leafNamespace] = make(map[string]any) + } + updsPerNs[leafNamespace][leafNodeName] = v + } + + for k, v := range updsPerNs { + updPath := &sdcpb.Path{Origin: k} + + updKey := k + ":" + rootNodeName + + singleUpd := map[string]any{} + singleUpd[updKey] = v + + singleUpdBytes, err := json.Marshal(singleUpd) + if err != nil { + return nil, err + } + updValue := &sdcpb.TypedValue{ + Value: &sdcpb.TypedValue_JsonIetfVal{ + JsonIetfVal: singleUpdBytes, + }, + } + + upds = append(upds, &sdcpb.Update{ + Path: updPath, + Value: updValue, + }) + } + } + } + + for _, delete := range deletes { + if len(delete.Elem) > 0 { + completePath := "" + found := false + var mostSpecificOrigin string + for _, elem := range delete.Elem { + if completePath != "" { + completePath += "/" + } + completePath += elem.Name + origin, f := nsMap[completePath] + if f { + found = true + mostSpecificOrigin = origin + } + } + if found { + delete.Origin = mostSpecificOrigin + } } - upds = []*sdcpb.Update{{Path: &sdcpb.Path{}, Value: &sdcpb.TypedValue{Value: &sdcpb.TypedValue_JsonIetfVal{JsonIetfVal: jsonBytes}}}} } case "proto": @@ -368,7 +450,7 @@ func (t *gnmiTarget) getSync(ctx context.Context, gnmiSync *config.SyncProtocol, req := &sdcpb.GetDataRequest{ Name: gnmiSync.Name, Path: paths, - DataType: sdcpb.DataType_CONFIG, + DataType: sdcpb.DataType_ALL, Encoding: sdcpb.Encoding(sdcpbEncoding(gnmiSync.Encoding)), } diff --git a/pkg/tree/validation_entry_leafref.go b/pkg/tree/validation_entry_leafref.go index 170abbe1..b1eff623 100644 --- a/pkg/tree/validation_entry_leafref.go +++ b/pkg/tree/validation_entry_leafref.go @@ -216,7 +216,7 @@ func (s *sharedEntryAttributes) validateLeafRefs(ctx context.Context, resultChan entry, err := s.NavigateLeafRef(ctx) if err != nil || len(entry) == 0 { // check if the OptionalInstance (!require-instances [https://datatracker.ietf.org/doc/html/rfc7950#section-9.9.3]) - if s.schema.GetField().GetType().GetOptionalInstance() { + if !s.schema.GetField().IsMandatory { generateOptionalWarning(ctx, s, lref, resultChan) return } diff --git a/pkg/utils/converter.go b/pkg/utils/converter.go index 26ee9212..9b061504 100644 --- a/pkg/utils/converter.go +++ b/pkg/utils/converter.go @@ -473,7 +473,13 @@ func convertStringToTv(schemaType *sdcpb.SchemaLeafType, v string, ts uint64) (* case "boolean": b, err := strconv.ParseBool(v) if err != nil { - return nil, err + if strings.Contains(strings.ToLower(v), "true") { + b = true + } else if strings.Contains(strings.ToLower(v), "false") { + b = false + } else { + return nil, err + } } return &sdcpb.TypedValue{ Timestamp: ts,