blob: 16e4dc491edb859545a3d532815f54e500a90282 [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 (
Scott Baker2c0ebda2019-05-06 16:55:47 -070020 "fmt"
Scott Baker2c0ebda2019-05-06 16:55:47 -070021 flags "github.com/jessevdk/go-flags"
22 "github.com/jhump/protoreflect/dynamic"
23 "github.com/opencord/cordctl/format"
Scott Baker6cf525a2019-05-09 12:25:08 -070024 "sort"
Scott Baker2c0ebda2019-05-06 16:55:47 -070025 "strings"
26)
27
28const (
Scott Baker6cf525a2019-05-09 12:25:08 -070029 DEFAULT_MODEL_AVAILABLE_FORMAT = "{{ . }}"
Scott Baker2c0ebda2019-05-06 16:55:47 -070030)
31
Scott Baker63ce82e2019-05-15 09:01:42 -070032type ModelNameString string
33
Scott Baker2c0ebda2019-05-06 16:55:47 -070034type ModelList struct {
35 OutputOptions
Scott Baker5201c0b2019-05-15 15:35:56 -070036 ShowHidden bool `long:"showhidden" description:"Show hidden fields in default output"`
37 ShowFeedback bool `long:"showfeedback" description:"Show feedback fields in default output"`
38 ShowBookkeeping bool `long:"showbookkeeping" description:"Show bookkeeping fields in default output"`
39 Filter string `long:"filter" description:"Comma-separated list of filters"`
Scott Baker6cf525a2019-05-09 12:25:08 -070040 Args struct {
Scott Baker63ce82e2019-05-15 09:01:42 -070041 ModelName ModelNameString
Scott Baker2c0ebda2019-05-06 16:55:47 -070042 } `positional-args:"yes" required:"yes"`
43}
44
Scott Baker6cf525a2019-05-09 12:25:08 -070045type ModelAvailable struct {
46 OutputOptions
47}
48
Scott Baker2c0ebda2019-05-06 16:55:47 -070049type ModelOpts struct {
Scott Baker6cf525a2019-05-09 12:25:08 -070050 List ModelList `command:"list"`
51 Available ModelAvailable `command:"available"`
Scott Baker2c0ebda2019-05-06 16:55:47 -070052}
53
54var modelOpts = ModelOpts{}
55
56func RegisterModelCommands(parser *flags.Parser) {
57 parser.AddCommand("model", "model commands", "Commands to query and manipulate XOS models", &modelOpts)
58}
59
Scott Baker6cf525a2019-05-09 12:25:08 -070060func (options *ModelAvailable) Execute(args []string) error {
61 conn, descriptor, err := InitReflectionClient()
Scott Baker2c0ebda2019-05-06 16:55:47 -070062 if err != nil {
63 return err
64 }
Scott Baker6cf525a2019-05-09 12:25:08 -070065
Scott Baker2c0ebda2019-05-06 16:55:47 -070066 defer conn.Close()
67
Scott Baker6cf525a2019-05-09 12:25:08 -070068 models, err := GetModelNames(descriptor)
Scott Baker2c0ebda2019-05-06 16:55:47 -070069 if err != nil {
70 return err
71 }
72
Scott Baker6cf525a2019-05-09 12:25:08 -070073 model_names := []string{}
74 for k := range models {
75 model_names = append(model_names, k)
76 }
77
78 sort.Strings(model_names)
79
80 outputFormat := CharReplacer.Replace(options.Format)
81 if outputFormat == "" {
82 outputFormat = DEFAULT_MODEL_AVAILABLE_FORMAT
83 }
84
85 result := CommandResult{
86 Format: format.Format(outputFormat),
87 OutputAs: toOutputType(options.OutputAs),
88 Data: model_names,
89 }
90
91 GenerateOutput(&result)
92
93 return nil
94}
95
96func (options *ModelList) Execute(args []string) error {
97 conn, descriptor, err := InitReflectionClient()
98 if err != nil {
99 return err
100 }
101
102 defer conn.Close()
103
Scott Baker63ce82e2019-05-15 09:01:42 -0700104 err = CheckModelName(descriptor, string(options.Args.ModelName))
Scott Baker6cf525a2019-05-09 12:25:08 -0700105 if err != nil {
106 return err
107 }
108
Scott Baker5201c0b2019-05-15 15:35:56 -0700109 var models []*dynamic.Message
Scott Baker6cf525a2019-05-09 12:25:08 -0700110
Scott Baker5201c0b2019-05-15 15:35:56 -0700111 queries, err := CommaSeparatedQueryToMap(options.Filter)
Scott Baker2c0ebda2019-05-06 16:55:47 -0700112 if err != nil {
113 return err
114 }
115
Scott Baker5201c0b2019-05-15 15:35:56 -0700116 if len(queries) == 0 {
117 models, err = ListModels(conn, descriptor, string(options.Args.ModelName))
118 } else {
119 models, err = FilterModels(conn, descriptor, string(options.Args.ModelName), queries)
Scott Baker2c0ebda2019-05-06 16:55:47 -0700120 }
Scott Baker2c0ebda2019-05-06 16:55:47 -0700121 if err != nil {
122 return err
123 }
124
125 field_names := make(map[string]bool)
Scott Baker5201c0b2019-05-15 15:35:56 -0700126 data := make([]map[string]interface{}, len(models))
127 for i, val := range models {
Scott Baker2c0ebda2019-05-06 16:55:47 -0700128 data[i] = make(map[string]interface{})
129 for _, field_desc := range val.GetKnownFields() {
130 field_name := field_desc.GetName()
Scott Baker2c0ebda2019-05-06 16:55:47 -0700131
132 isGuiHidden := strings.Contains(field_desc.GetFieldOptions().String(), "1005:1")
133 isFeedback := strings.Contains(field_desc.GetFieldOptions().String(), "1006:1")
134 isBookkeeping := strings.Contains(field_desc.GetFieldOptions().String(), "1007:1")
135
136 if isGuiHidden && (!options.ShowHidden) {
137 continue
138 }
139
140 if isFeedback && (!options.ShowFeedback) {
141 continue
142 }
143
Scott Baker6cf525a2019-05-09 12:25:08 -0700144 if isBookkeeping && (!options.ShowBookkeeping) {
Scott Baker2c0ebda2019-05-06 16:55:47 -0700145 continue
146 }
147
148 if field_desc.IsRepeated() {
149 continue
150 }
151
Scott Baker6cf525a2019-05-09 12:25:08 -0700152 data[i][field_name] = val.GetFieldByName(field_name)
Scott Baker2c0ebda2019-05-06 16:55:47 -0700153
154 field_names[field_name] = true
155 }
156 }
157
158 var default_format strings.Builder
159 default_format.WriteString("table")
160 first := true
161 for field_name, _ := range field_names {
162 if first {
163 fmt.Fprintf(&default_format, "{{ .%s }}", field_name)
164 first = false
165 } else {
166 fmt.Fprintf(&default_format, "\t{{ .%s }}", field_name)
167 }
168 }
169
170 outputFormat := CharReplacer.Replace(options.Format)
171 if outputFormat == "" {
172 outputFormat = default_format.String()
173 }
174 if options.Quiet {
175 outputFormat = "{{.Id}}"
176 }
177
178 result := CommandResult{
179 Format: format.Format(outputFormat),
180 OutputAs: toOutputType(options.OutputAs),
181 Data: data,
182 }
183
184 GenerateOutput(&result)
185 return nil
186}
Scott Baker63ce82e2019-05-15 09:01:42 -0700187
188func (modelName *ModelNameString) Complete(match string) []flags.Completion {
189 conn, descriptor, err := InitReflectionClient()
190 if err != nil {
191 return nil
192 }
193
194 defer conn.Close()
195
196 models, err := GetModelNames(descriptor)
197 if err != nil {
198 return nil
199 }
200
201 list := make([]flags.Completion, 0)
202 for k := range models {
203 if strings.HasPrefix(k, match) {
204 list = append(list, flags.Completion{Item: k})
205 }
206 }
207
208 return list
209}