The following are a few examples on how to use the Golang API generated from the onos-topo
gRPC API.
All the examples assume that the following import is available:
import "github.com/onosproject/onos-api/go/topo"
Similarly, all examples assume that the TopoService
client has been obtained and that context ctx
was
either provided or created via code similar to the following:
client := topo.CreateTopoClient(conn)
...
ctx := context.Background()
The following example shows how to create an Entity
of e2cell
kind, with a couple of separate aspects of
information - Location
, Coverage
and E2Cell
:
cell := &topo.Object{
ID: topo.ID(cellID),
Type: topo.Object_ENTITY,
Obj: &topo.Object_Entity{
Entity: &topo.Entity{
KindID: topo.ID(topo.E2CELL),
},
}
}
cell.SetAspect(&topo.Location{Lat: 50.08834, Lng: 14.40372})
cell.SetAspect(&topo.Coverage{Height: 8.7, ArcWidth: 120.0, Azimuth: 315.0, Tilt: -5.0})
cell.SetAspect(&topo.E2Cell{CellObjectID: "4269A20", AntennaCount: 5, EARFCN: 69, PCI: 42, CellType: "FEMTO"})
resp, err := client.Create(ctx, &topo.CreateRequest{Object: cell})
Here we can see an example of creating Relation
of neighbors
kind, representing one cell being a neighbor
of another. There are no aspects annotating this relation. Also, note that if the relation ID is unspecified
during the creation, one will be automatically generated using the topo.RelationID(...)
method, based on
the source, kind and the target IDs.
relation := &topo.Object{
Type: topo.Object_RELATION,
Obj: &topo.Object_Relation{
Entity: &topo.Relation{
KindID: topo.ID(topo.NEIGHBORS),
SrcEntityID: cellID,
TgtEntityID: neighborCellID,
},
}
}
resp, err := client.Create(ctx, &topo.CreateRequest{Object: relation})
In order to retrieve a specific object, one must simply provide its ID. To access a specific aspect, create
an instance of the aspect object and pass its reference to the GetAspect
method of the topology object:
cell, err := client.Get(ctx, &topo.GetRequest{ID: cellID})
if err == nil { ... }
coverage := &topo.Coverage{}
cell.GetAspect(coverage)
To update an aspect of an object, one must first obtain the object via Get
, update its structure and
then call the Update
method:
cell, err := client.Get(&topo.GetRequest{ID: cellID})
if err == nil { ... }
cell.SetAspect(&topo.Location{Lat: 50.08834, Lng: 14.40372})
resp, err := client.Update(ctx, &topo.UpdateRequest{Object: cell})
The List
method can be used to obtain various collections of objects using Filters
specified as part of
the request. Presently, there are several types of filters.
- Object Type filter - specifies which types of objects are relevant
- Entity or Relation Kind filter - specifies which kinds of entities or relations are relevant
- Label filters - specifies criteria to filter on specific labels and their values
- Relation filter - allows finding objects related to another object via a particular kind of relation
The object kind and label filters can specify values via equal
, in
and not
operators.
Furthermore, the results can be optionally sorted (ascending or descending) by the ID of the objects. This can be useful for applications where determinism in the returned results is desirable.
Here is an example of requesting only Entity
objects, of either e2node
or e2cell
kind, sorted in the
ascending order of their IDs:
filters := &topo.Filters{
KindFilter: &topoapi.Filter{
Filter: &topoapi.Filter_In{In: &topoapi.InFilter{Values: []string{topo.E2NODE, topo.E2CELL}}},
},
}
resp, err := client.List(ctx, &topo.ListRequest{Filters: filters, SortOrder: topo.SortOrder_ASCENDING})
The following shows how to obtain an unordered list of e2cell
entities, related to a specified node entity
using a contains
relation:
resp, err := client.List(ctx, &topo.ListRequest{Filters: &topo.Filters{
RelationFilter: &topo.RelationFilter{
SrcId: nodeID,
RelationKind: topo.CONTAINS,
TargetKind: topo.E2CELL,
},
}})
The topology API allows clients to watch the changes in real-time via its Watch
method which delivers its
results as a continuous stream of events. These include not only the usual create
, update
, and delete
events,
but also replay
events to indicate the object as it existed prior to the Watch
being called.
As with the List
method, the results can be further narrowed by specifying Filters
in the request.
Here is a simple example of the Watch
usage, which does not specify any filters:
stream, err := client.Watch(ctx, &topo.WatchRequest{})
if err == nil { ... }
for {
msg, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil { ... }
processEvent(msg.Event.Type, msg.Event.Object)
}
The client can cancel the watch at anytime by invoking ctx.Done()
.
Deleting an object requires to merely provide its ID:
node, err := client.Delete(ctx, &topo.DeleteRequest{ID: nodeID})
if err == nil { ... }