forked from sonic-net/sonic-mgmt-framework
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #248 from project-arlo/brcm_poc1101
Brcm poc1101
- Loading branch information
Showing
53 changed files
with
3,213 additions
and
594 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
.debhelper/ | ||
files | ||
sonic-mgmt-framework.debhelper.log | ||
sonic-mgmt-framework.substvars | ||
sonic-mgmt-framework/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
################################################################################ | ||
# # | ||
# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # | ||
# its subsidiaries. # | ||
# # | ||
# Licensed under the Apache License, Version 2.0 (the "License"); # | ||
# you may not use this file except in compliance with the License. # | ||
# You may obtain a copy of the License at # | ||
# # | ||
# http://www.apache.org/licenses/LICENSE-2.0 # | ||
# # | ||
# Unless required by applicable law or agreed to in writing, software # | ||
# distributed under the License is distributed on an "AS IS" BASIS, # | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # | ||
# See the License for the specific language governing permissions and # | ||
# limitations under the License. # | ||
# # | ||
################################################################################ | ||
|
||
# Build time configurations for swagger codegen | ||
# Use makefile syntax | ||
|
||
## | ||
# YANGAPI_EXCLUDES indicates the yang modules to be excluded from codegen. | ||
# Server and client code will not be generated for these yangs modules. | ||
# By default server code will be generated for all yangs under models/yang | ||
# and models/yang/sonic directories. Note that each entry should be yang | ||
# module name which is used for generated yaml file name. | ||
YANGAPI_EXCLUDES += | ||
|
||
## | ||
# PY_YANGAPI_CLIENTS indicates the yang modules for which python client | ||
# sdk code should be generated. By default client sdk code will not be | ||
# generated to save build time and space. YANGAPI_EXCLUDES has priority | ||
# over this list. Note that the entry should be the yang module name | ||
# which is used for generated yaml file name. | ||
PY_YANGAPI_CLIENTS += openconfig-interfaces | ||
PY_YANGAPI_CLIENTS += openconfig-lldp | ||
PY_YANGAPI_CLIENTS += openconfig-platform | ||
PY_YANGAPI_CLIENTS += openconfig-system | ||
PY_YANGAPI_CLIENTS += openconfig-spanning-tree | ||
PY_YANGAPI_CLIENTS += sonic-vxlan | ||
PY_YANGAPI_CLIENTS += sonic-sflow | ||
|
||
## | ||
# OPENAPI_EXCLUDES indicates the OpenAPI specs to be excluded from codegen. | ||
# By default all yaml files under models/openapi directory are considered | ||
# for codegen. Items should be the yaml file name without the .yaml extension. | ||
# Eg: vlan.yaml should be specified as "OPENAPI_EXCLUDES += vlan" | ||
OPENAPI_EXCLUDES += | ||
|
||
## | ||
# PY_OPENAPI_CLIENTS indicates the OpenAPI specs for which python client | ||
# sdk code should be generated. By default client sdk code is not generated. | ||
# Items should be the yaml file name without the .yaml extension. Note | ||
# that OPENAPI_EXCLUDES has priority over this list. | ||
PY_OPENAPI_CLIENTS += | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
diff --git a/node.go b/node.go | ||
index 76032bb..9960c17 100644 | ||
--- a/node.go | ||
+++ b/node.go | ||
@@ -110,6 +110,17 @@ func parseValue(x interface{}, top *Node, level int) { | ||
addNode(n) | ||
parseValue(vv, n, level+1) | ||
} | ||
+ case map[string]string: | ||
+ var keys []string | ||
+ for key := range v { | ||
+ keys = append(keys, key) | ||
+ } | ||
+ sort.Strings(keys) | ||
+ for _, key := range keys { | ||
+ n := &Node{Data: key, Type: ElementNode, level: level} | ||
+ addNode(n) | ||
+ parseValue(v[key], n, level+1) | ||
+ } | ||
case map[string]interface{}: | ||
// The Go’s map iteration order is random. | ||
// (https://blog.golang.org/go-maps-in-action#Iteration-order) | ||
@@ -155,3 +166,9 @@ func Parse(r io.Reader) (*Node, error) { | ||
} | ||
return parse(b) | ||
} | ||
+ | ||
+func ParseJsonMap(jsonMap *map[string]interface{}) (*Node, error) { | ||
+ doc := &Node{Type: DocumentNode} | ||
+ parseValue(*jsonMap, doc, 1) | ||
+ return doc, nil | ||
+} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,88 @@ | ||
# Generic RESTful Python client | ||
# Generic REST Client for CLI | ||
|
||
A generic RESTful Python client for interacting with JSON APIs. | ||
Actioner scripts can use the generic rest client **cli_client.py** to communicate to REST Server. | ||
This client is tailor made to connect to local REST Server and handle the CLI actioner usecases. | ||
All future CLI-REST integration enhancements (for RBAC) can be handled in this tool without | ||
affecting individual actioner scripts. | ||
|
||
## Usage | ||
To use this tool, first create an `ApiClient` object. | ||
|
||
To use this client you just need to import ApiClient and initialize it with an URL endpoint | ||
```python | ||
import cli_client as cc | ||
|
||
from cli_client import ApiClient | ||
api = ApiClient('#your_api_endpoint') #your_api_endpoint is optional default is https://localhost:443 | ||
api = cc.ApiClient() | ||
``` | ||
|
||
Now that you have a RESTful API object you can start sending requests. | ||
Create a path object for target REST resource. It accepts parameterized path template and parameter | ||
values. Path template is similar to the template used by swagger. Parameter values will be URL-encoded | ||
and substituted in the template to get REST resource path. | ||
|
||
```python | ||
path = cc.Path('/restconf/data/openconfig-acl:acl/acl-sets/acl-set={name},{type}/acl-entries', | ||
name='MyNewAccessList', type='ACL_IPV4') | ||
``` | ||
|
||
## Making a request | ||
Invoke REST API.. `ApiClient` object supports get, post, put, patch and delete operations. | ||
All these operations send a REST request and return a response object wrapping the REST response data. | ||
|
||
The framework supports GET, PUT, POST, PATCH and DELETE requests: | ||
```python | ||
response = api.get(path) | ||
``` | ||
|
||
from cli_client import ApiClient | ||
api = ApiClient() | ||
response = api.get('/authors/') | ||
response = api.post('/authors/', {'title': 'Broadcom', 'author': 'Faraaz Mohammed'}) | ||
response = api.put('/author/faraaz/', {'dob': '06/09/2006'}) | ||
response = api.delete('/author/faraaz/') | ||
Check API status through `response.ok()` function, which returns true if API was success - REST server | ||
returned HTTP 2xx status code. `ok()` function returns false if server returned any other status response. | ||
|
||
## To get the Response Data | ||
response = api.get('/authors/') | ||
Use response.content object | ||
```python | ||
if response.ok() { | ||
respJson = response.content | ||
# invoke renderer to display respJson | ||
} else { | ||
print response.error_message() | ||
} | ||
``` | ||
|
||
For Successful request response.content will contain valid JSON data | ||
For Non-Successful request response.content will contain errors object returned by REST Server | ||
If request was successful, `response.content` will hold the response data as JSON dictionary object. | ||
If request failed, `response.content` will hold error JSON returned by the server. CLI displayable | ||
error message can be extracted using `response.error_message()` function. | ||
|
||
## Verifying Requests | ||
Examples of other REST API calls. | ||
|
||
Two helpers are built in to verify the success of requests made. `ok()` checks for a 20x status code and returns a boolean, `errors()` returns the body content as a dict object if the status code is not 20x: | ||
```python | ||
jsonDict = {} | ||
jsonDict["acl-set"]=[{ "name":the_acl_name, .... }] # construct your request data json | ||
|
||
response = api.get('/books/') | ||
if response.ok(): | ||
print 'Success!' | ||
else: | ||
print req.errors() | ||
# POST request | ||
response = api.post(path, data=jsonDict) | ||
|
||
# PUT request | ||
reponse = api.put(path, data=jsonDict) | ||
|
||
# PATCH request | ||
response = api.patch(path, data=jsonDict) | ||
|
||
# DELETE request | ||
response = api.delete(path) | ||
``` | ||
|
||
Above example used `response.error_message()` function to get ser displayable error message from | ||
the REST response. REST server always returns error information in standard RESTCONF error format. | ||
The `error_message()` function looks for the **error-message** attribute to get user displayable message. | ||
A generic message will be returned based on **error-tag** attribute value if there was no **error-message** | ||
attribute. This can be customized through an error formatter function as shown below. | ||
Default error formatter is sufficient for most of the cases. | ||
|
||
```python | ||
if not response.ok(): | ||
print response.error_message(formatter_func=my_new_error_message_formatter) | ||
``` | ||
|
||
The custom formtter function would receive RESTCONF error json and should return a string. | ||
Below is a sample implementation which uses error-type attribute to format an error message. | ||
|
||
```python | ||
def my_new_error_message_formatter(error_entry): | ||
if err_entry['error-type'] == 'protocol': | ||
return "System error.. Please reboot!!" | ||
return "Application error.. Please retry." | ||
``` | ||
|
Oops, something went wrong.