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

Query Parameter support in transformer infra for REST GET operation #102

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
353fe57
Transformer infra enhacements to support singleton container
ranjinidn May 25, 2023
8aee902
Sonic yang singleton container support in GET and SET/CRU code flow
amrutasali May 25, 2023
64a4736
Added a container in openconfig-test-xfmr.yang that maps to a sonic y…
amrutasali May 25, 2023
b2ff5db
Add sonic singleton container in sonic yang and UT cases for CRUD and…
ranjinidn May 25, 2023
b200825
Update unit test README file with the build tag information
ranjinidn Jun 2, 2023
33dead7
Merge branch 'master' into transformerinfra_sonicyang_singleton_conta…
ranjinidn Jun 7, 2023
ff58508
Initial Query Params infra support in translib and common app
ranjinidn Jun 9, 2023
5a6b62a
Support for depth query parameter in transformer infra
ranjinidn Jun 9, 2023
9ad1f3f
Merge branch 'master' into transformerinfra_query_parameter_support
amrutasali Jun 22, 2023
9d743da
Content query parameter support in xfmr infra
amrutasali Jun 24, 2023
5da6650
Add fields query parameters support
ranjinidn Jul 13, 2023
97e5f58
Merge branch 'master' into transformerinfra_query_parameter_support
amrutasali Aug 15, 2023
086c338
Query parameter pruning API integration and error handling
amrutasali Aug 16, 2023
8ba20d9
1)Handle query-parameter content mismatch check for list node since t…
amrutasali Aug 22, 2023
c7c532e
Merge branch 'master' into transformerinfra_query_parameter_support
amrutasali Aug 23, 2023
ceaebcd
added query-parameter support in transformer test infra
amrutasali Aug 24, 2023
f51f0b0
Merge branch 'master' into transformerinfra_query_parameter_support
amrutasali Aug 30, 2023
c303f69
fixed build error due to rebase/merge-conflict resolution
amrutasali Aug 30, 2023
0ca8c8e
Add UT cases for depth and content query parameters support in infra
ranjinidn Aug 30, 2023
0410366
Add UT cases for depth and content query parameters support in infra …
amrutasali Aug 31, 2023
3c8b8ae
Add OC yang fields query parameters unit tests
ranjinidn Sep 1, 2023
c9f591b
Added sonic yang fields query-parameter UT cases
amrutasali Sep 1, 2023
38b4bfd
Infra enhancement for handling OC Yang list/config/key-leaf & list/st…
amrutasali Sep 8, 2023
4d50723
Add composite key handling changes for 1:1 OC to sonic key mapping
ranjinidn Sep 8, 2023
c946358
wMerge branch 'transformerinfra_query_parameter_support' of github.co…
ranjinidn Sep 8, 2023
b6d02e1
Run format check on test yang UT file, Move composite Key handling in…
ranjinidn Sep 8, 2023
f550482
Merge branch 'master' into transformerinfra_query_parameter_support
amrutasali Sep 11, 2023
0a5015d
Merge branch 'master' into transformerinfra_query_parameter_support
amrutasali Sep 13, 2023
f70dfb3
when filling the list-keys in GET flow, update the list-keys map used…
amrutasali Sep 13, 2023
64904d9
Merge branch 'transformerinfra_query_parameter_support' of github.com…
amrutasali Sep 13, 2023
3bc2e43
Merge branch 'master' into transformerinfra_query_parameter_support
amrutasali Sep 19, 2023
410eb9e
Merge branch 'master' into transformerinfra_query_parameter_support
amrutasali Sep 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions translib/api_tests_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ func (app *apiTests) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (
resp["message"] = app.echoMsg
resp["path"] = app.path
resp["depth"] = app.depth
resp["content"] = app.content
resp["fields"] = app.fields

gr.Payload, err = json.Marshal(&resp)
return gr, err
Expand Down
18 changes: 14 additions & 4 deletions translib/app_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,20 @@ type appData struct {
// These include RESTCONF query parameters like - depth, fields etc.
type appOptions struct {

// depth limits subtree levels in the response data.
// 0 indicates unlimited depth.
// Valid for GET API only.
depth uint
// depth limits subtree levels in the response data.
// 0 indicates unlimited depth.
// Valid for GET API only.
depth uint

// content query parameter value receved from the URI
// possible value is one of 'config', 'nonconfig','all','state' or 'operational'
// Valid for GET API only.
content string

//fields query parameters
// paths of the fields that needs to be filtered in GET payload response
// Valid for GET API only.
fields []string

// deleteEmptyEntry indicates if the db entry should be deleted upon
// deletion of last field. This is a non standard option.
Expand Down
40 changes: 33 additions & 7 deletions translib/common_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,24 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType)
origXfmrYgotRoot, _ := ygot.DeepCopy((*app.ygotRoot).(ygot.GoStruct))
isEmptyPayload := false
appYgotStruct := (*app.ygotRoot).(ygot.GoStruct)
payload, isEmptyPayload, err = transformer.GetAndXlateFromDB(app.pathInfo.Path, &appYgotStruct, dbs, txCache)
var qParams transformer.QueryParams
qParams, err = transformer.NewQueryParams(app.depth, app.content, app.fields)
if err != nil {
log.Warning("transformer.NewQueryParams() returned : ", err)
resPayload = []byte("{}")
break
}
payload, isEmptyPayload, err = transformer.GetAndXlateFromDB(app.pathInfo.Path, &appYgotStruct, dbs, txCache, qParams)
if err != nil {
// target URI for list GET request with QP content!=all and node's content-type mismatches the requested content-type, return empty payload
if isEmptyPayload && qParams.IsContentEnabled() && transformer.IsListNode(app.pathInfo.Path) {
if err.Error() == transformer.QUERY_CONTENT_MISMATCH_ERR {
err = nil
}
}
if err != nil {
log.Warning("transformer.GetAndXlateFromDB() returned : ", err)
}
resPayload = payload
break
}
Expand All @@ -429,6 +445,12 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType)
resPayload = payload
break
}
if isEmptyPayload && (app.depth == 1) && !transformer.IsLeafNode(app.pathInfo.Path) && !transformer.IsLeafListNode(app.pathInfo.Path) {
// target URI for Container or list GET request with depth = 1, returns empty payload
resPayload = payload
break
}

targetObj, tgtObjCastOk := (*app.ygotTarget).(ygot.GoStruct)
if !tgtObjCastOk {
/*For ygotTarget populated by tranlib, for query on leaf level and list(without instance) level,
Expand Down Expand Up @@ -476,13 +498,17 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType)
err = tlerr.NotFound("Resource not found")
break
}
resPayload = payload
log.Info("No data available")
//TODO: Return not found error
//err = tlerr.NotFound("Resource not found")
break
if !qParams.IsEnabled() {
resPayload = payload
log.Info("No data available")
//TODO: Return not found error
//err = tlerr.NotFound("Resource not found")
break
}
}
if !qParams.IsEnabled() {
resYgot = appYgotStruct
}
resYgot = appYgotStruct
}
}
if resYgot != nil {
Expand Down
6 changes: 3 additions & 3 deletions translib/transformer/sflow_openconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func Test_node_on_openconfig_sflow(t *testing.T) {
loadDB(db.ConfigDB, pre_req_map)
expected_get_json := "{\"openconfig-sampling-sflow:state\":{\"agent\":\"Ethernet8\",\"enabled\":true,\"polling-interval\":300}}"
url = "/openconfig-sampling-sflow:sampling/sflow/state"
t.Run("Test get on sflow node", processGetRequest(url, expected_get_json, false))
t.Run("Test get on sflow node", processGetRequest(url, nil, expected_get_json, false))
time.Sleep(1 * time.Second)
unloadDB(db.ConfigDB, cleanuptbl)
t.Log("\n\n+++++++++++++ Done Performing Get on Sflow node ++++++++++++")
Expand Down Expand Up @@ -154,7 +154,7 @@ func Test_node_openconfig_sflow_collector(t *testing.T) {
loadDB(db.ConfigDB, pre_req_map)
expected_get_json := "{ \"openconfig-sampling-sflow:collectors\":{\"collector\":[{\"address\":\"3.3.3.3\",\"config\":{\"address\":\"3.3.3.3\",\"network-instance\":\"default\",\"port\":6666},\"network-instance\":\"default\",\"port\":6666,\"state\":{\"address\":\"3.3.3.3\",\"network-instance\":\"default\",\"port\":6666}}]}}"
url = "/openconfig-sampling-sflow:sampling/sflow/collectors"
t.Run("Test get on collector node for sflow", processGetRequest(url, expected_get_json, false))
t.Run("Test get on collector node for sflow", processGetRequest(url, nil, expected_get_json, false))
time.Sleep(1 * time.Second)
cleanuptbl = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"3.3.3.3_6666_default": ""}}
unloadDB(db.ConfigDB, cleanuptbl)
Expand Down Expand Up @@ -215,7 +215,7 @@ func Test_node_openconfig_sflow_interface(t *testing.T) {
loadDB(db.ApplDB, non_pre_req_map)
expected_get_json := "{\"openconfig-sampling-sflow:state\":{\"enabled\":true,\"name\":\"Ethernet8\",\"sampling-rate\":30000}}"
url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet8]/state"
t.Run("Test get on sflow interface", processGetRequest(url, expected_get_json, false))
t.Run("Test get on sflow interface", processGetRequest(url, nil, expected_get_json, false))
time.Sleep(2 * time.Second)
cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet8": ""}}
unloadDB(db.ConfigDB, cleanuptbl)
Expand Down
12 changes: 6 additions & 6 deletions translib/transformer/sflow_sonic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func Test_node_sonic_sflow(t *testing.T) {
// Verify global configurations
url = "/sonic-sflow:sonic-sflow/SFLOW/global"
url_body_json = "{\"sonic-sflow:global\":{\"admin_state\":\"up\",\"agent_id\":\"Ethernet4\",\"polling_interval\":100}}"
t.Run("Verify sFlow global configurations", processGetRequest(url, url_body_json, false))
t.Run("Verify sFlow global configurations", processGetRequest(url, nil, url_body_json, false))

//Delete sflow global configurations
url = "/sonic-sflow:sonic-sflow/SFLOW"
Expand All @@ -68,7 +68,7 @@ func Test_node_sonic_sflow(t *testing.T) {
//Verify deleted sflow global configuration
url = "/sonic-sflow:sonic-sflow/SFLOW"
url_body_json = "{}"
t.Run("Verify delete on sflow node", processGetRequest(url, url_body_json, false))
t.Run("Verify delete on sflow node", processGetRequest(url, nil, url_body_json, false))
}

func Test_node_sonic_sflow_collector(t *testing.T) {
Expand All @@ -82,7 +82,7 @@ func Test_node_sonic_sflow_collector(t *testing.T) {

// Verify sFlow collector configurations
url = "/sonic-sflow:sonic-sflow/SFLOW_COLLECTOR/SFLOW_COLLECTOR_LIST[name=1.1.1.1_6343_default]"
t.Run("Verify sFlow collector", processGetRequest(url, url_body_json, false))
t.Run("Verify sFlow collector", processGetRequest(url, nil, url_body_json, false))

// Set collector ip
url = "/sonic-sflow:sonic-sflow/SFLOW_COLLECTOR/SFLOW_COLLECTOR_LIST[name=1.1.1.1_6343_default]/collector_ip"
Expand All @@ -104,7 +104,7 @@ func Test_node_sonic_sflow_collector(t *testing.T) {
//Verify collector port
url = "/sonic-sflow:sonic-sflow/SFLOW_COLLECTOR/SFLOW_COLLECTOR_LIST"
url_body_json = "{}"
t.Run("Verify delete on sFlow collector", processGetRequest(url, url_body_json, false))
t.Run("Verify delete on sFlow collector", processGetRequest(url, nil, url_body_json, false))
}

func Test_node_sonic_sflow_interface(t *testing.T) {
Expand Down Expand Up @@ -137,7 +137,7 @@ func Test_node_sonic_sflow_interface(t *testing.T) {
url_body_json = "{}"
err_str := "Resource not found"
expected_err := tlerr.NotFoundError{Format: err_str}
t.Run("Verify delete on sFlow Interface", processGetRequest(url, url_body_json, true, expected_err))
t.Run("Verify delete on sFlow Interface", processGetRequest(url, nil, url_body_json, true, expected_err))

//Delete sflow global configurations
url = "/sonic-sflow:sonic-sflow/SFLOW"
Expand All @@ -147,5 +147,5 @@ func Test_node_sonic_sflow_interface(t *testing.T) {
//Verify deleted sflow global configuration
url = "/sonic-sflow:sonic-sflow/SFLOW"
url_body_json = "{}"
t.Run("Verify delete on sFlow collector", processGetRequest(url, url_body_json, false))
t.Run("Verify delete on sFlow collector", processGetRequest(url, nil, url_body_json, false))
}
18 changes: 6 additions & 12 deletions translib/transformer/test/openconfig-test-xfmr-annot.yang
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,12 @@ module openconfig-test-xfmr-annot {
}
}

deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:config/oc-test-xfmr:id {
deviate add {
sonic-ext:field-transformer "test_sensor_group_id_field_xfmr";
}
}

deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:config/oc-test-xfmr:group-colors {
deviate add {
sonic-ext:field-name "colors";
}
}

deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:state/oc-test-xfmr:id {
deviate add {
sonic-ext:field-transformer "test_sensor_group_id_field_xfmr";
}
}

deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:state/oc-test-xfmr:group-colors {
deviate add {
sonic-ext:field-name "colors";
Expand Down Expand Up @@ -90,6 +78,12 @@ module openconfig-test-xfmr-annot {
}
}

deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-components/oc-test-xfmr:test-sensor-component {
deviate add {
sonic-ext:table-name "TEST_SENSOR_COMPONENT_TABLE";
}
}

deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set {
deviate add {
sonic-ext:table-name "TEST_SET_TABLE";
Expand Down
125 changes: 123 additions & 2 deletions translib/transformer/test/openconfig-test-xfmr.yang
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ module openconfig-test-xfmr {
}
}
}
uses test-sensor-components-top;
}
}
}
Expand Down Expand Up @@ -274,7 +275,9 @@ module openconfig-test-xfmr {
}
}
}

////////////////////////////

grouping test-sensor-group-config {
description
"Config parameters related to the test sensor groups";
Expand Down Expand Up @@ -370,6 +373,126 @@ module openconfig-test-xfmr {

}

///////////////////
grouping test-sensor-component-config {
description
"Configuration data for sensor-components";

leaf name {
type string;
description
"Device name for the sensor component. ";
}
leaf type {
type enumeration {
enum TYPE1 {
description
"Component Type 1.";
}
enum TYPE2 {
description
"Component Type 2.";
}
enum TYPE3 {
description
"Component Type 3.";
}
}
}
leaf version {
type string;
description
"Version of the Component. ";
}
leaf description {
type string;
description
"Description, or comment, for the test sensor component";
}
}

grouping test-sensor-component-state {
description
"Operational State data for sensor components";
leaf mfg-name {
type string;
description
"System-supplied identifier for the manufacturer of the component.";
}

leaf mfg-date {
type string;
description
"System-supplied representation of the component's
manufacturing date.";
}

leaf hardware-version {
type string;
description
"For hardware components, this is the hardware revision of
the component.";
}

leaf firmware-version {
type string;
description
"For hardware components, this is the version of associated
firmware that is running on the component, if applicable.";
}
}

grouping test-sensor-components-top {
container test-sensor-components {
description
"Enclosing container for test sensor component references";

list test-sensor-component {
key "name type version";
description
"List of sensor component references";

leaf name {
type leafref {
path "../config/name";
}
description
"Reference to the name of component";
}

leaf type {
type leafref {
path "../config/type";
}
description
"Reference to the type of component";
}

leaf version {
type leafref {
path "../config/version";
}
description
"Reference to the version of component";
}

container config {
description
"Configuration parameters to configure a sensor component";
uses test-sensor-component-config;
}

container state {
config false;
description
"Operational state parameters of a sensor component";
uses test-sensor-component-config;
uses test-sensor-component-state;
}
}
}
}

grouping interfaces-config {
description
"Configuration data for interface references";
Expand Down Expand Up @@ -424,10 +547,8 @@ module openconfig-test-xfmr {
}
}
}

///////////////////


// data definition statements

container test-xfmr {
Expand Down
23 changes: 23 additions & 0 deletions translib/transformer/test/sonic-test-xfmr.yang
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,29 @@ module sonic-test-xfmr {
}
}

container TEST_SENSOR_COMPONENT_TABLE {

list TEST_SENSOR_COMPONENT_TABLE_LIST {
key "name type version";

leaf name {
type string;
}

leaf type {
type string;
}

leaf version {
type string;
}

leaf description {
type string;
}
}
}

container TEST_SET_TABLE {

list TEST_SET_TABLE_LIST {
Expand Down
Loading