blob: f7a1963426bf24b40322f514e1ebac0c982f0776 [file] [log] [blame]
Scott Baker2c0ebda2019-05-06 16:55:47 -07001/*
2 * Portions copyright 2019-present Open Networking Foundation
3 * Original copyright 2019-present Ciena Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package commands
18
19import (
20 "context"
21 "fmt"
22 "github.com/fullstorydev/grpcurl"
Scott Baker2c0ebda2019-05-06 16:55:47 -070023 flags "github.com/jessevdk/go-flags"
24 "github.com/jhump/protoreflect/dynamic"
25 "github.com/opencord/cordctl/format"
Scott Baker6cf525a2019-05-09 12:25:08 -070026 "sort"
Scott Baker2c0ebda2019-05-06 16:55:47 -070027 "strings"
28)
29
30const (
Scott Baker6cf525a2019-05-09 12:25:08 -070031 DEFAULT_MODEL_AVAILABLE_FORMAT = "{{ . }}"
Scott Baker2c0ebda2019-05-06 16:55:47 -070032)
33
Scott Baker63ce82e2019-05-15 09:01:42 -070034type ModelNameString string
35
Scott Baker2c0ebda2019-05-06 16:55:47 -070036type ModelList struct {
37 OutputOptions
Scott Baker6cf525a2019-05-09 12:25:08 -070038 ShowHidden bool `long:"showhidden" description:"Show hidden fields in default output"`
39 ShowFeedback bool `long:"showfeedback" description:"Show feedback fields in default output"`
40 ShowBookkeeping bool `long:"showbookkeeping" description:"Show bookkeeping fields in default output"`
41 Args struct {
Scott Baker63ce82e2019-05-15 09:01:42 -070042 ModelName ModelNameString
Scott Baker2c0ebda2019-05-06 16:55:47 -070043 } `positional-args:"yes" required:"yes"`
44}
45
Scott Baker6cf525a2019-05-09 12:25:08 -070046type ModelAvailable struct {
47 OutputOptions
48}
49
Scott Baker2c0ebda2019-05-06 16:55:47 -070050type ModelOpts struct {
Scott Baker6cf525a2019-05-09 12:25:08 -070051 List ModelList `command:"list"`
52 Available ModelAvailable `command:"available"`
Scott Baker2c0ebda2019-05-06 16:55:47 -070053}
54
55var modelOpts = ModelOpts{}
56
57func RegisterModelCommands(parser *flags.Parser) {
58 parser.AddCommand("model", "model commands", "Commands to query and manipulate XOS models", &modelOpts)
59}
60
Scott Baker6cf525a2019-05-09 12:25:08 -070061func (options *ModelAvailable) Execute(args []string) error {
62 conn, descriptor, err := InitReflectionClient()
Scott Baker2c0ebda2019-05-06 16:55:47 -070063 if err != nil {
64 return err
65 }
Scott Baker6cf525a2019-05-09 12:25:08 -070066
Scott Baker2c0ebda2019-05-06 16:55:47 -070067 defer conn.Close()
68
Scott Baker6cf525a2019-05-09 12:25:08 -070069 models, err := GetModelNames(descriptor)
Scott Baker2c0ebda2019-05-06 16:55:47 -070070 if err != nil {
71 return err
72 }
73
Scott Baker6cf525a2019-05-09 12:25:08 -070074 model_names := []string{}
75 for k := range models {
76 model_names = append(model_names, k)
77 }
78
79 sort.Strings(model_names)
80
81 outputFormat := CharReplacer.Replace(options.Format)
82 if outputFormat == "" {
83 outputFormat = DEFAULT_MODEL_AVAILABLE_FORMAT
84 }
85
86 result := CommandResult{
87 Format: format.Format(outputFormat),
88 OutputAs: toOutputType(options.OutputAs),
89 Data: model_names,
90 }
91
92 GenerateOutput(&result)
93
94 return nil
95}
96
97func (options *ModelList) Execute(args []string) error {
98 conn, descriptor, err := InitReflectionClient()
99 if err != nil {
100 return err
101 }
102
103 defer conn.Close()
104
Scott Baker63ce82e2019-05-15 09:01:42 -0700105 err = CheckModelName(descriptor, string(options.Args.ModelName))
Scott Baker6cf525a2019-05-09 12:25:08 -0700106 if err != nil {
107 return err
108 }
109
Scott Baker63ce82e2019-05-15 09:01:42 -0700110 method := "xos.xos/List" + string(options.Args.ModelName)
Scott Baker6cf525a2019-05-09 12:25:08 -0700111
Scott Baker2c0ebda2019-05-06 16:55:47 -0700112 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
113 defer cancel()
114
115 headers := GenerateHeaders()
116
117 h := &RpcEventHandler{}
118 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, headers, h, h.GetParams)
119 if err != nil {
120 return err
121 }
122
123 if h.Status != nil && h.Status.Err() != nil {
124 return h.Status.Err()
125 }
126
127 d, err := dynamic.AsDynamicMessage(h.Response)
128 if err != nil {
129 return err
130 }
131
132 items, err := d.TryGetFieldByName("items")
133 if err != nil {
134 return err
135 }
136
137 field_names := make(map[string]bool)
138 data := make([]map[string]interface{}, len(items.([]interface{})))
139 for i, item := range items.([]interface{}) {
140 val := item.(*dynamic.Message)
141 data[i] = make(map[string]interface{})
142 for _, field_desc := range val.GetKnownFields() {
143 field_name := field_desc.GetName()
Scott Baker2c0ebda2019-05-06 16:55:47 -0700144
145 isGuiHidden := strings.Contains(field_desc.GetFieldOptions().String(), "1005:1")
146 isFeedback := strings.Contains(field_desc.GetFieldOptions().String(), "1006:1")
147 isBookkeeping := strings.Contains(field_desc.GetFieldOptions().String(), "1007:1")
148
149 if isGuiHidden && (!options.ShowHidden) {
150 continue
151 }
152
153 if isFeedback && (!options.ShowFeedback) {
154 continue
155 }
156
Scott Baker6cf525a2019-05-09 12:25:08 -0700157 if isBookkeeping && (!options.ShowBookkeeping) {
Scott Baker2c0ebda2019-05-06 16:55:47 -0700158 continue
159 }
160
161 if field_desc.IsRepeated() {
162 continue
163 }
164
Scott Baker6cf525a2019-05-09 12:25:08 -0700165 data[i][field_name] = val.GetFieldByName(field_name)
Scott Baker2c0ebda2019-05-06 16:55:47 -0700166
167 field_names[field_name] = true
168 }
169 }
170
171 var default_format strings.Builder
172 default_format.WriteString("table")
173 first := true
174 for field_name, _ := range field_names {
175 if first {
176 fmt.Fprintf(&default_format, "{{ .%s }}", field_name)
177 first = false
178 } else {
179 fmt.Fprintf(&default_format, "\t{{ .%s }}", field_name)
180 }
181 }
182
183 outputFormat := CharReplacer.Replace(options.Format)
184 if outputFormat == "" {
185 outputFormat = default_format.String()
186 }
187 if options.Quiet {
188 outputFormat = "{{.Id}}"
189 }
190
191 result := CommandResult{
192 Format: format.Format(outputFormat),
193 OutputAs: toOutputType(options.OutputAs),
194 Data: data,
195 }
196
197 GenerateOutput(&result)
198 return nil
199}
Scott Baker63ce82e2019-05-15 09:01:42 -0700200
201func (modelName *ModelNameString) Complete(match string) []flags.Completion {
202 conn, descriptor, err := InitReflectionClient()
203 if err != nil {
204 return nil
205 }
206
207 defer conn.Close()
208
209 models, err := GetModelNames(descriptor)
210 if err != nil {
211 return nil
212 }
213
214 list := make([]flags.Completion, 0)
215 for k := range models {
216 if strings.HasPrefix(k, match) {
217 list = append(list, flags.Completion{Item: k})
218 }
219 }
220
221 return list
222}