| // Copyright 2018-present Open Networking Foundation |
| // Copyright 2018-present Edgecore Networks Corporation |
| // |
| // 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. |
| |
| package main |
| |
| import ( |
| "encoding/json" |
| logrus "github.com/sirupsen/logrus" |
| "io/ioutil" |
| "net/http" |
| ) |
| |
| /* parse_map() parses the json structure, amap, and returns all sub-folder paths found at the 2nd level of the multiplayer structure |
| */ |
| func parse_map(amap map[string]interface{}, level uint, archive map[string]bool) (paths []string) { |
| level = level + 1 |
| for key, val := range amap { |
| switch val.(type) { |
| case map[string]interface{}: |
| p := parse_map(val.(map[string]interface{}), level, archive) |
| paths = append(paths, p...) |
| case []interface{}: |
| p := parse_array(val.([]interface{}), level, archive) |
| paths = append(paths, p...) |
| default: |
| if level == 2 && key == "@odata.id" { |
| /* sub-folder path of a resource can be found as the value of the key '@odata.id' showing up at the 2nd level of the data read from a resource. When a path is found, it's checked against the array 'archive' to avoid duplicates. */ |
| if _, ok := archive[val.(string)]; !ok { |
| archive[val.(string)] = true |
| paths = append(paths, val.(string)) |
| } |
| } |
| } |
| } |
| return paths |
| } |
| |
| /* parse_array() parses any vlaue, if in the form of an array, of a key-value pair found in the json structure, and returns any paths found. |
| */ |
| func parse_array(anarray []interface{}, level uint, archive map[string]bool) (paths []string) { |
| for _, val := range anarray { |
| switch val.(type) { |
| case map[string]interface{}: |
| p := parse_map(val.(map[string]interface{}), level, archive) |
| paths = append(paths, p...) |
| } |
| } |
| return paths |
| } |
| |
| /* read_resource() reads data from the specified Redfish resource, including its sub-folders, of the specified device ip and rerutnrs the data read. |
| |
| Based on careful examination of the data returned from several resources sampled, it was determined that sub-folder paths can be found as the value to the key '@odata.id' showing up at the 2nd level of the data read from a resource. |
| */ |
| func read_resource(ip string, resource string, archive map[string]bool) (data []string) { |
| resp, err := http.Get(ip + resource) |
| if resp != nil { |
| defer resp.Body.Close() |
| } |
| if err != nil { |
| logrus.Errorf("Error http get %s", err) |
| return |
| } |
| body, err := ioutil.ReadAll(resp.Body) |
| if err != nil { |
| logrus.Errorf("Error Read %s", err) |
| return |
| } |
| |
| data = append(data, string(body)) |
| |
| m := map[string]interface{}{} |
| err = json.Unmarshal([]byte(body), &m) |
| if err != nil { |
| logrus.Errorf("Error Unmarshal %s", err) |
| return |
| } |
| |
| resources := parse_map(m, 0, archive) |
| |
| for _, resource := range resources { |
| d := read_resource(ip, resource, archive) |
| data = append(data, d...) |
| } |
| return data |
| } |
| |
| /* sample JSON files can be found in the samples folder */ |
| func (s *Server) get_status(ip string, resource string) (data []string) { |
| archive := make(map[string]bool) |
| base_ip := RF_DEFAULT_PROTOCOL + ip |
| /* 'archive' maintains a list of all resources that will be/have been visited to avoid duplicates */ |
| archive[resource] = true |
| data = read_resource(base_ip, resource, archive) |
| return data |
| } |