Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
gNMI Target
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
danet
gNMI Target
Commits
59e3ab15
Verified
Commit
59e3ab15
authored
1 year ago
by
Malte Bauch
Browse files
Options
Downloads
Patches
Plain Diff
Use ytypes.UnmarshalSetRequest for SetRequest
parent
078bab5a
No related branches found
No related tags found
No related merge requests found
Pipeline
#189020
failed
1 year ago
Stage: build
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
internal/gnmiserver/model.go
+5
-3
5 additions, 3 deletions
internal/gnmiserver/model.go
internal/gnmiserver/server.go
+17
-351
17 additions, 351 deletions
internal/gnmiserver/server.go
target.go
+1
-1
1 addition, 1 deletion
target.go
with
23 additions
and
355 deletions
internal/gnmiserver/model.go
+
5
−
3
View file @
59e3ab15
...
@@ -35,17 +35,19 @@ type GoStructEnumData map[string]map[int64]ygot.EnumDefinition
...
@@ -35,17 +35,19 @@ type GoStructEnumData map[string]map[int64]ygot.EnumDefinition
type
Model
struct
{
type
Model
struct
{
modelData
[]
*
pb
.
ModelData
modelData
[]
*
pb
.
ModelData
structRootType
reflect
.
Type
structRootType
reflect
.
Type
schemaTree
map
[
string
]
*
yang
.
Entry
schemaTreeRoot
*
yang
.
Entry
schemaTreeRoot
*
yang
.
Entry
jsonUnmarshaler
JSON
Unmarshal
er
jsonUnmarshaler
ytypes
.
Unmarshal
Func
enumData
GoStructEnumData
enumData
GoStructEnumData
}
}
// NewModel returns an instance of Model struct.
// NewModel returns an instance of Model struct.
func
NewModel
(
m
[]
*
pb
.
ModelData
,
t
reflect
.
Type
,
r
*
y
ang
.
Entry
,
f
JSON
Unmarshal
er
,
e
GoStructEnumData
)
*
Model
{
func
NewModel
(
m
[]
*
pb
.
ModelData
,
t
reflect
.
Type
,
st
*
y
types
.
Schema
,
f
ytypes
.
Unmarshal
Func
,
e
GoStructEnumData
)
*
Model
{
return
&
Model
{
return
&
Model
{
modelData
:
m
,
modelData
:
m
,
structRootType
:
t
,
structRootType
:
t
,
schemaTreeRoot
:
r
,
schemaTree
:
st
.
SchemaTree
,
schemaTreeRoot
:
st
.
RootSchema
(),
jsonUnmarshaler
:
f
,
jsonUnmarshaler
:
f
,
enumData
:
e
,
enumData
:
e
,
}
}
...
...
This diff is collapsed.
Click to expand it.
internal/gnmiserver/server.go
+
17
−
351
View file @
59e3ab15
...
@@ -23,7 +23,6 @@ import (
...
@@ -23,7 +23,6 @@ import (
"fmt"
"fmt"
"io"
"io"
"reflect"
"reflect"
"strconv"
"time"
"time"
"golang.org/x/net/context"
"golang.org/x/net/context"
...
@@ -204,213 +203,6 @@ func (s *Server) checkEncodingAndModel(encoding pb.Encoding, models []*pb.ModelD
...
@@ -204,213 +203,6 @@ func (s *Server) checkEncodingAndModel(encoding pb.Encoding, models []*pb.ModelD
return
nil
return
nil
}
}
// doDelete deletes the path from the json tree if the path exists. If success,
// it calls the callback function to apply the change to the device hardware.
func
(
s
*
Server
)
doDelete
(
jsonTree
map
[
string
]
interface
{},
prefix
,
path
*
pb
.
Path
)
(
*
pb
.
UpdateResult
,
error
)
{
// Update json tree of the device config
var
curNode
interface
{}
=
jsonTree
pathDeleted
:=
false
fullPath
:=
gnmiFullPath
(
prefix
,
path
)
schema
:=
s
.
model
.
schemaTreeRoot
for
i
,
elem
:=
range
fullPath
.
Elem
{
// Delete sub-tree or leaf node.
node
,
ok
:=
curNode
.
(
map
[
string
]
interface
{})
if
!
ok
{
break
}
// Delete node
if
i
==
len
(
fullPath
.
Elem
)
-
1
{
if
elem
.
GetKey
()
==
nil
{
delete
(
node
,
elem
.
Name
)
pathDeleted
=
true
break
}
pathDeleted
=
deleteKeyedListEntry
(
node
,
elem
)
break
}
if
curNode
,
schema
=
getChildNode
(
node
,
schema
,
elem
,
false
);
curNode
==
nil
{
break
}
}
if
reflect
.
DeepEqual
(
fullPath
,
pbRootPath
)
{
// Delete root
for
k
:=
range
jsonTree
{
delete
(
jsonTree
,
k
)
}
}
//// Apply the validated operation to the config tree and device.
if
pathDeleted
{
// newConfig, err := s.toGoStruct(jsonTree)
// if err != nil {
// return nil, status.Error(codes.Internal, err.Error())
// }
// if s.callback != nil {
// if applyErr := s.callback(newConfig); applyErr != nil {
// if rollbackErr := s.callback(s.config); rollbackErr != nil {
// return nil, status.Errorf(codes.Internal, "error in rollback the failed operation (%v): %v", applyErr, rollbackErr)
// }
// return nil, status.Errorf(codes.Aborted, "error in applying operation to device: %v", applyErr)
// }
// }
}
return
&
pb
.
UpdateResult
{
Path
:
path
,
Op
:
pb
.
UpdateResult_DELETE
,
},
nil
}
// doReplaceOrUpdate validates the replace or update operation to be applied to
// the device, modifies the json tree of the config struct, then calls the
// callback function to apply the operation to the device hardware.
func
(
s
*
Server
)
doReplaceOrUpdate
(
jsonTree
map
[
string
]
interface
{},
op
pb
.
UpdateResult_Operation
,
prefix
,
path
*
pb
.
Path
,
val
*
pb
.
TypedValue
)
(
*
pb
.
UpdateResult
,
error
)
{
// Validate the operation.
fullPath
:=
gnmiFullPath
(
prefix
,
path
)
emptyNode
,
entry
,
err
:=
ytypes
.
GetOrCreateNode
(
s
.
model
.
schemaTreeRoot
,
s
.
model
.
newRootValue
(),
fullPath
)
if
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
NotFound
,
"path %v is not found in the config structure: %v"
,
fullPath
,
err
)
}
if
entry
.
ReadOnly
()
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"It is not possible to change the value of a config false field at path: %s"
,
entry
.
Path
())
}
jsonIETFValue
:=
val
.
GetJsonIetfVal
()
var
nodeVal
interface
{}
nodeStruct
,
ok
:=
emptyNode
.
(
ygot
.
ValidatedGoStruct
)
if
ok
{
if
err
:=
s
.
model
.
jsonUnmarshaler
(
jsonIETFValue
,
nodeStruct
);
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"unmarshaling json data to config struct fails: %v"
,
err
)
}
if
err
:=
nodeStruct
.
Validate
();
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"config data validation fails: %v"
,
err
)
}
var
err
error
if
nodeVal
,
err
=
ygot
.
ConstructIETFJSON
(
nodeStruct
,
&
ygot
.
RFC7951JSONConfig
{});
err
!=
nil
{
msg
:=
fmt
.
Sprintf
(
"error in constructing IETF JSON tree from config struct: %v"
,
err
)
log
.
Error
(
msg
)
return
nil
,
status
.
Error
(
codes
.
Internal
,
msg
)
}
}
else
{
var
err
error
if
nodeVal
,
err
=
value
.
ToScalar
(
val
);
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"cannot convert leaf node to scalar type: %v"
,
err
)
}
}
// Check if val contains config false fields and return an error if thats
// the case.
if
nodeStruct
!=
nil
{
nodeStructCopy
,
err
:=
ygot
.
DeepCopy
(
nodeStruct
)
if
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"could not create a deep copy of current nodeStruct: %v"
,
err
)
}
if
err
:=
ygot
.
PruneConfigFalse
(
entry
,
nodeStruct
);
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed prune config false for nodeStruct: %v"
,
err
)
}
diff
,
err
:=
ygot
.
Diff
(
nodeStructCopy
,
nodeStruct
)
if
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed to create a diff for nodeStruct: %v"
,
err
)
}
if
diff
!=
nil
&&
len
(
diff
.
Delete
)
!=
0
{
paths
:=
make
([]
string
,
0
)
for
_
,
path
:=
range
diff
.
Delete
{
p
,
err
:=
ygot
.
PathToString
(
path
)
if
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed to create string from path: %v"
,
err
)
}
paths
=
append
(
paths
,
p
)
}
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"Can not set config false paths: %v"
,
paths
)
}
}
else
if
entry
.
ReadOnly
()
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"It is not possible to change the value of a config false field at path: %s"
,
entry
.
Path
())
}
// Update json tree of the device config.
var
curNode
interface
{}
=
jsonTree
schema
:=
s
.
model
.
schemaTreeRoot
for
i
,
elem
:=
range
fullPath
.
Elem
{
switch
node
:=
curNode
.
(
type
)
{
case
map
[
string
]
interface
{}
:
// Set node value.
if
node
!=
nil
{
if
i
==
len
(
fullPath
.
Elem
)
-
1
{
if
elem
.
GetKey
()
==
nil
{
if
grpcStatusError
:=
setPathWithoutAttribute
(
op
,
node
,
elem
,
nodeVal
);
grpcStatusError
!=
nil
{
return
nil
,
grpcStatusError
}
break
}
if
grpcStatusError
:=
setPathWithAttribute
(
op
,
node
,
elem
,
nodeVal
);
grpcStatusError
!=
nil
{
return
nil
,
grpcStatusError
}
break
}
logrus
.
Debug
(
"doReplaceOrUpdate, node: "
,
node
)
if
curNode
,
schema
=
getChildNode
(
node
,
schema
,
elem
,
true
);
curNode
==
nil
{
return
nil
,
status
.
Errorf
(
codes
.
NotFound
,
"path elem not found: %v"
,
elem
)
}
}
else
{
logrus
.
Debugf
(
"node is nil for path elem: %s"
,
elem
.
String
())
}
case
[]
interface
{}
:
return
nil
,
status
.
Errorf
(
codes
.
NotFound
,
"incompatible path elem: %v"
,
elem
)
default
:
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"wrong node type: %T"
,
curNode
)
}
}
if
reflect
.
DeepEqual
(
fullPath
,
pbRootPath
)
{
// Replace/Update root.
if
op
==
pb
.
UpdateResult_UPDATE
{
return
nil
,
status
.
Error
(
codes
.
Unimplemented
,
"update the root of config tree is unsupported"
)
}
nodeValAsTree
,
ok
:=
nodeVal
.
(
map
[
string
]
interface
{})
if
!
ok
{
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"expect a tree to replace the root, got a scalar value: %T"
,
nodeVal
)
}
for
k
:=
range
jsonTree
{
delete
(
jsonTree
,
k
)
}
for
k
,
v
:=
range
nodeValAsTree
{
jsonTree
[
k
]
=
v
}
}
//newConfig, err := s.toGoStruct(jsonTree)
//if err != nil {
// return nil, status.Error(codes.Internal, err.Error())
//}
//// Apply the validated operation to the device.
//if s.callback != nil {
// if applyErr := s.callback(newConfig); applyErr != nil {
// if rollbackErr := s.callback(s.config); rollbackErr != nil {
// return nil, status.Errorf(codes.Internal, "error in rollback the failed operation (%v): %v", applyErr, rollbackErr)
// }
// return nil, status.Errorf(codes.Aborted, "error in applying operation to device: %v", applyErr)
// }
//}
return
&
pb
.
UpdateResult
{
Path
:
path
,
Op
:
op
,
},
nil
}
func
(
s
*
Server
)
toGoStruct
(
jsonTree
map
[
string
]
interface
{})
(
ygot
.
ValidatedGoStruct
,
error
)
{
jsonDump
,
err
:=
json
.
Marshal
(
jsonTree
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error in marshaling IETF JSON tree to bytes: %v"
,
err
)
}
goStruct
,
err
:=
s
.
model
.
NewConfigStruct
(
jsonDump
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error in creating config struct from IETF JSON data: %v"
,
err
)
}
return
goStruct
,
nil
}
// getGNMIServiceVersion returns a pointer to the gNMI service version string.
// getGNMIServiceVersion returns a pointer to the gNMI service version string.
// The method is non-trivial because of the way it is defined in the proto file.
// The method is non-trivial because of the way it is defined in the proto file.
func
getGNMIServiceVersion
()
(
*
string
,
error
)
{
func
getGNMIServiceVersion
()
(
*
string
,
error
)
{
...
@@ -432,51 +224,6 @@ func getGNMIServiceVersion() (*string, error) {
...
@@ -432,51 +224,6 @@ func getGNMIServiceVersion() (*string, error) {
return
ver
.
(
*
string
),
nil
return
ver
.
(
*
string
),
nil
}
}
// deleteKeyedListEntry deletes the keyed list entry from node that matches the
// path elem. If the entry is the only one in keyed list, deletes the entire
// list. If the entry is found and deleted, the function returns true. If it is
// not found, the function returns false.
func
deleteKeyedListEntry
(
node
map
[
string
]
interface
{},
elem
*
pb
.
PathElem
)
bool
{
curNode
,
ok
:=
node
[
elem
.
Name
]
if
!
ok
{
return
false
}
keyedList
,
ok
:=
curNode
.
([]
interface
{})
if
!
ok
{
return
false
}
for
i
,
n
:=
range
keyedList
{
m
,
ok
:=
n
.
(
map
[
string
]
interface
{})
if
!
ok
{
log
.
Errorf
(
"expect map[string]interface{} for a keyed list entry, got %T"
,
n
)
return
false
}
keyMatching
:=
true
for
k
,
v
:=
range
elem
.
Key
{
attrVal
,
ok
:=
m
[
k
]
if
!
ok
{
return
false
}
if
v
!=
fmt
.
Sprintf
(
"%v"
,
attrVal
)
{
keyMatching
=
false
break
}
}
if
keyMatching
{
listLen
:=
len
(
keyedList
)
if
listLen
==
1
{
delete
(
node
,
elem
.
Name
)
return
true
}
keyedList
[
i
]
=
keyedList
[
listLen
-
1
]
node
[
elem
.
Name
]
=
keyedList
[
0
:
listLen
-
1
]
return
true
}
}
return
false
}
// gnmiFullPath builds the full path from the prefix and path.
// gnmiFullPath builds the full path from the prefix and path.
func
gnmiFullPath
(
prefix
,
path
*
pb
.
Path
)
*
pb
.
Path
{
func
gnmiFullPath
(
prefix
,
path
*
pb
.
Path
)
*
pb
.
Path
{
fullPath
:=
&
pb
.
Path
{
Origin
:
path
.
Origin
}
fullPath
:=
&
pb
.
Path
{
Origin
:
path
.
Origin
}
...
@@ -489,73 +236,6 @@ func gnmiFullPath(prefix, path *pb.Path) *pb.Path {
...
@@ -489,73 +236,6 @@ func gnmiFullPath(prefix, path *pb.Path) *pb.Path {
return
fullPath
return
fullPath
}
}
// isNIl checks if an interface is nil or its value is nil.
func
isNil
(
i
interface
{})
bool
{
if
i
==
nil
{
return
true
}
switch
kind
:=
reflect
.
ValueOf
(
i
)
.
Kind
();
kind
{
case
reflect
.
Chan
,
reflect
.
Func
,
reflect
.
Interface
,
reflect
.
Map
,
reflect
.
Ptr
,
reflect
.
Slice
:
return
reflect
.
ValueOf
(
i
)
.
IsNil
()
default
:
return
false
}
}
// setPathWithAttribute replaces or updates a child node of curNode in the IETF
// JSON config tree, where the child node is indexed by pathElem with attribute.
// The function returns grpc status error if unsuccessful.
func
setPathWithAttribute
(
op
pb
.
UpdateResult_Operation
,
curNode
map
[
string
]
interface
{},
pathElem
*
pb
.
PathElem
,
nodeVal
interface
{})
error
{
nodeValAsTree
,
ok
:=
nodeVal
.
(
map
[
string
]
interface
{})
if
!
ok
{
return
status
.
Errorf
(
codes
.
InvalidArgument
,
"expect nodeVal is a json node of map[string]interface{}, received %T"
,
nodeVal
)
}
m
:=
getKeyedListEntry
(
curNode
,
pathElem
,
true
)
if
m
==
nil
{
return
status
.
Errorf
(
codes
.
NotFound
,
"path elem not found: %v"
,
pathElem
)
}
if
op
==
pb
.
UpdateResult_REPLACE
{
for
k
:=
range
m
{
delete
(
m
,
k
)
}
}
for
attrKey
,
attrVal
:=
range
pathElem
.
GetKey
()
{
m
[
attrKey
]
=
attrVal
if
asNum
,
err
:=
strconv
.
ParseFloat
(
attrVal
,
64
);
err
==
nil
{
m
[
attrKey
]
=
asNum
}
for
k
,
v
:=
range
nodeValAsTree
{
if
k
==
attrKey
&&
fmt
.
Sprintf
(
"%v"
,
v
)
!=
attrVal
{
return
status
.
Errorf
(
codes
.
InvalidArgument
,
"invalid config data: %v is a path attribute"
,
k
)
}
}
}
for
k
,
v
:=
range
nodeValAsTree
{
m
[
k
]
=
v
}
return
nil
}
// setPathWithoutAttribute replaces or updates a child node of curNode in the
// IETF config tree, where the child node is indexed by pathElem without
// attribute. The function returns grpc status error if unsuccessful.
func
setPathWithoutAttribute
(
op
pb
.
UpdateResult_Operation
,
curNode
map
[
string
]
interface
{},
pathElem
*
pb
.
PathElem
,
nodeVal
interface
{})
error
{
target
,
hasElem
:=
curNode
[
pathElem
.
Name
]
nodeValAsTree
,
nodeValIsTree
:=
nodeVal
.
(
map
[
string
]
interface
{})
if
op
==
pb
.
UpdateResult_REPLACE
||
!
hasElem
||
!
nodeValIsTree
{
curNode
[
pathElem
.
Name
]
=
nodeVal
return
nil
}
targetAsTree
,
ok
:=
target
.
(
map
[
string
]
interface
{})
if
!
ok
{
return
status
.
Errorf
(
codes
.
Internal
,
"error in setting path: expect map[string]interface{} to update, got %T"
,
target
)
}
for
k
,
v
:=
range
nodeValAsTree
{
targetAsTree
[
k
]
=
v
}
return
nil
}
// Capabilities returns supported encodings and supported models.
// Capabilities returns supported encodings and supported models.
func
(
s
*
Server
)
Capabilities
(
ctx
context
.
Context
,
req
*
pb
.
CapabilityRequest
)
(
*
pb
.
CapabilityResponse
,
error
)
{
func
(
s
*
Server
)
Capabilities
(
ctx
context
.
Context
,
req
*
pb
.
CapabilityRequest
)
(
*
pb
.
CapabilityResponse
,
error
)
{
ver
,
err
:=
getGNMIServiceVersion
()
ver
,
err
:=
getGNMIServiceVersion
()
...
@@ -691,52 +371,38 @@ func (s *Server) Set(ctx context.Context, req *pb.SetRequest) (*pb.SetResponse,
...
@@ -691,52 +371,38 @@ func (s *Server) Set(ctx context.Context, req *pb.SetRequest) (*pb.SetResponse,
s
.
config
.
Lock
()
s
.
config
.
Lock
()
defer
s
.
config
.
Unlock
()
defer
s
.
config
.
Unlock
()
logrus
.
Debug
(
"Current data: "
,
s
.
config
.
Data
)
logrus
.
Debug
(
"Incoming Set Request: "
,
req
)
// Obtain current configuration as JSON
jsonTree
,
err
:=
ygot
.
ConstructIETFJSON
(
s
.
config
.
Data
,
&
ygot
.
RFC7951JSONConfig
{})
if
err
!=
nil
{
msg
:=
fmt
.
Sprintf
(
"error in constructing IETF JSON tree from config struct: %v"
,
err
)
log
.
Error
(
msg
)
return
nil
,
status
.
Error
(
codes
.
Internal
,
msg
)
}
prefix
:=
req
.
GetPrefix
()
var
results
[]
*
pb
.
UpdateResult
var
results
[]
*
pb
.
UpdateResult
for
_
,
path
:=
range
req
.
GetDelete
()
{
newConfig
,
err
:=
ygot
.
DeepCopy
(
s
.
config
.
Data
)
res
,
grpcStatusError
:=
s
.
doDelete
(
jsonTree
,
prefix
,
path
)
if
err
!=
nil
{
if
grpcStatusError
!=
nil
{
return
nil
,
status
.
Error
(
codes
.
Internal
,
err
.
Error
())
return
nil
,
grpcStatusError
}
results
=
append
(
results
,
res
)
}
for
_
,
upd
:=
range
req
.
GetReplace
()
{
res
,
grpcStatusError
:=
s
.
doReplaceOrUpdate
(
jsonTree
,
pb
.
UpdateResult_REPLACE
,
prefix
,
upd
.
GetPath
(),
upd
.
GetVal
())
if
grpcStatusError
!=
nil
{
return
nil
,
grpcStatusError
}
results
=
append
(
results
,
res
)
}
}
for
_
,
upd
:=
range
req
.
GetUpdate
()
{
res
,
grpcStatusError
:=
s
.
doReplaceOrUpdate
(
jsonTree
,
pb
.
UpdateResult_UPDATE
,
prefix
,
upd
.
GetPath
(),
upd
.
GetVal
())
newSchema
:=
&
ytypes
.
Schema
{
if
grpcStatusError
!=
nil
{
Root
:
newConfig
,
return
nil
,
grpcStatusError
SchemaTree
:
s
.
model
.
schemaTree
,
}
Unmarshal
:
s
.
model
.
jsonUnmarshaler
,
results
=
append
(
results
,
res
)
}
}
newConfig
,
err
:
=
s
.
toGoStruct
(
jsonT
re
e
)
err
=
ytypes
.
UnmarshalSetRequest
(
newSchema
,
re
q
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
status
.
Error
(
codes
.
Internal
,
err
.
Error
())
return
nil
,
status
.
Error
(
codes
.
Internal
,
err
.
Error
())
}
}
valNewConfig
,
ok
:=
newConfig
.
(
ygot
.
ValidatedGoStruct
)
if
!
ok
{
return
nil
,
status
.
Error
(
codes
.
Internal
,
fmt
.
Sprintf
(
"wrong type for new config, expected: %T; got: %T"
,
(
ygot
.
ValidatedGoStruct
)(
nil
),
newConfig
))
}
currentConfig
,
err
:=
ygot
.
DeepCopy
(
s
.
config
.
Data
)
currentConfig
,
err
:=
ygot
.
DeepCopy
(
s
.
config
.
Data
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
status
.
Error
(
codes
.
Internal
,
err
.
Error
())
return
nil
,
status
.
Error
(
codes
.
Internal
,
err
.
Error
())
}
}
// Apply the validated operations to the device.
// Apply the validated operations to the device.
diff
,
applyErr
:=
s
.
callback
(
n
ewConfig
,
currentConfig
.
(
ygot
.
ValidatedGoStruct
))
diff
,
applyErr
:=
s
.
callback
(
valN
ewConfig
,
currentConfig
.
(
ygot
.
ValidatedGoStruct
))
if
applyErr
!=
nil
{
if
applyErr
!=
nil
{
if
_
,
rollbackErr
:=
s
.
callback
(
currentConfig
.
(
ygot
.
ValidatedGoStruct
),
s
.
config
.
Data
);
rollbackErr
!=
nil
{
if
_
,
rollbackErr
:=
s
.
callback
(
currentConfig
.
(
ygot
.
ValidatedGoStruct
),
s
.
config
.
Data
);
rollbackErr
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"error in rollback the failed operation (%v): %v"
,
applyErr
,
rollbackErr
)
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"error in rollback the failed operation (%v): %v"
,
applyErr
,
rollbackErr
)
...
@@ -744,7 +410,7 @@ func (s *Server) Set(ctx context.Context, req *pb.SetRequest) (*pb.SetResponse,
...
@@ -744,7 +410,7 @@ func (s *Server) Set(ctx context.Context, req *pb.SetRequest) (*pb.SetResponse,
return
nil
,
status
.
Errorf
(
codes
.
Aborted
,
"error in applying operation to device: %v"
,
applyErr
)
return
nil
,
status
.
Errorf
(
codes
.
Aborted
,
"error in applying operation to device: %v"
,
applyErr
)
}
}
s
.
config
.
Data
=
n
ewConfig
s
.
config
.
Data
=
valN
ewConfig
// notify subscribers about the changes
// notify subscribers about the changes
err
=
s
.
PublishNotificationsToSubscribers
(
diff
)
err
=
s
.
PublishNotificationsToSubscribers
(
diff
)
...
...
This diff is collapsed.
Click to expand it.
target.go
+
1
−
1
View file @
59e3ab15
...
@@ -63,7 +63,7 @@ func (gt *GnmiTarget) Start(bindAddress string, certFile string, keyFile string,
...
@@ -63,7 +63,7 @@ func (gt *GnmiTarget) Start(bindAddress string, certFile string, keyFile string,
gnmiModel
:=
server
.
NewModel
(
gt
.
modeldata
,
gnmiModel
:=
server
.
NewModel
(
gt
.
modeldata
,
// NOTE: could be problematic
// NOTE: could be problematic
reflect
.
TypeOf
(
gt
.
model
),
reflect
.
TypeOf
(
gt
.
model
),
gt
.
schema
.
RootSchema
()
,
gt
.
schema
,
gt
.
unmarshalFn
,
gt
.
unmarshalFn
,
gt
.
ΛEnum
)
gt
.
ΛEnum
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment