blob: 233116338620b01b216d1450e714ce291d66adb4 [file] [log] [blame]
Zack Williamse940c7a2019-08-21 14:25:39 -07001/*
2 * Copyright 2019-present Ciena Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package commands
17
18import (
19 "encoding/json"
20 "fmt"
Scott Baker2b0ad652019-08-21 14:57:07 -070021 "github.com/opencord/voltctl/pkg/filter"
22 "github.com/opencord/voltctl/pkg/format"
23 "github.com/opencord/voltctl/pkg/order"
Zack Williamse940c7a2019-08-21 14:25:39 -070024 "google.golang.org/grpc"
25 "gopkg.in/yaml.v2"
26 "io/ioutil"
27 "log"
28 "os"
29 "path/filepath"
30 "strings"
31 "time"
32)
33
34type OutputType uint8
35
36const (
37 OUTPUT_TABLE OutputType = iota
38 OUTPUT_JSON
39 OUTPUT_YAML
40)
41
42type GrpcConfigSpec struct {
43 Timeout time.Duration `yaml:"timeout"`
44}
45
46type TlsConfigSpec struct {
47 UseTls bool `yaml:"useTls"`
48 CACert string `yaml:"caCert"`
49 Cert string `yaml:"cert"`
50 Key string `yaml:"key"`
51 Verify string `yaml:"verify"`
52}
53
54type GlobalConfigSpec struct {
55 ApiVersion string `yaml:"apiVersion"`
56 Server string `yaml:"server"`
57 Tls TlsConfigSpec `yaml:"tls"`
58 Grpc GrpcConfigSpec `yaml:"grpc"`
59 K8sConfig string `yaml:"-"`
60}
61
62var (
63 ParamNames = map[string]map[string]string{
64 "v1": {
65 "ID": "voltha.ID",
66 },
67 "v2": {
68 "ID": "common.ID",
69 },
70 }
71
72 CharReplacer = strings.NewReplacer("\\t", "\t", "\\n", "\n")
73
74 GlobalConfig = GlobalConfigSpec{
David Bainbridgec4029aa2019-09-26 18:56:39 +000075 ApiVersion: "v2",
Zack Williamse940c7a2019-08-21 14:25:39 -070076 Server: "localhost",
77 Tls: TlsConfigSpec{
78 UseTls: false,
79 },
80 Grpc: GrpcConfigSpec{
81 Timeout: time.Second * 10,
82 },
83 }
84
85 GlobalOptions struct {
David Bainbridgec4029aa2019-09-26 18:56:39 +000086 Config string `short:"c" long:"config" env:"VOLTCONFIG" value-name:"FILE" default:"" description:"Location of client config file"`
87 Server string `short:"s" long:"server" default:"" value-name:"SERVER:PORT" description:"IP/Host and port of VOLTHA"`
88 // Do not set the default for the API version here, else it will override the value read in the config
Zack Williamse940c7a2019-08-21 14:25:39 -070089 ApiVersion string `short:"a" long:"apiversion" description:"API version" value-name:"VERSION" choice:"v1" choice:"v2"`
90 Debug bool `short:"d" long:"debug" description:"Enable debug mode"`
91 UseTLS bool `long:"tls" description:"Use TLS"`
92 CACert string `long:"tlscacert" value-name:"CA_CERT_FILE" description:"Trust certs signed only by this CA"`
93 Cert string `long:"tlscert" value-name:"CERT_FILE" description:"Path to TLS vertificate file"`
94 Key string `long:"tlskey" value-name:"KEY_FILE" description:"Path to TLS key file"`
95 Verify bool `long:"tlsverify" description:"Use TLS and verify the remote"`
96 K8sConfig string `short:"8" long:"k8sconfig" env:"KUBECONFIG" value-name:"FILE" default:"" description:"Location of Kubernetes config file"`
97 }
98)
99
100type OutputOptions struct {
101 Format string `long:"format" value-name:"FORMAT" default:"" description:"Format to use to output structured data"`
102 Quiet bool `short:"q" long:"quiet" description:"Output only the IDs of the objects"`
103 OutputAs string `short:"o" long:"outputas" default:"table" choice:"table" choice:"json" choice:"yaml" description:"Type of output to generate"`
104 NameLimit int `short:"l" long:"namelimit" default:"-1" value-name:"LIMIT" description:"Limit the depth (length) in the table column name"`
105}
106
107type ListOutputOptions struct {
108 OutputOptions
109 Filter string `short:"f" long:"filter" default:"" value-name:"FILTER" description:"Only display results that match filter"`
110 OrderBy string `short:"r" long:"orderby" default:"" value-name:"ORDER" description:"Specify the sort order of the results"`
111}
112
113type OutputOptionsJson struct {
114 Format string `long:"format" value-name:"FORMAT" default:"" description:"Format to use to output structured data"`
115 Quiet bool `short:"q" long:"quiet" description:"Output only the IDs of the objects"`
116 OutputAs string `short:"o" long:"outputas" default:"json" choice:"table" choice:"json" choice:"yaml" description:"Type of output to generate"`
117 NameLimit int `short:"l" long:"namelimit" default:"-1" value-name:"LIMIT" description:"Limit the depth (length) in the table column name"`
118}
119
120type ListOutputOptionsJson struct {
121 OutputOptionsJson
122 Filter string `short:"f" long:"filter" default:"" value-name:"FILTER" description:"Only display results that match filter"`
123 OrderBy string `short:"r" long:"orderby" default:"" value-name:"ORDER" description:"Specify the sort order of the results"`
124}
125
126func toOutputType(in string) OutputType {
127 switch in {
128 case "table":
129 fallthrough
130 default:
131 return OUTPUT_TABLE
132 case "json":
133 return OUTPUT_JSON
134 case "yaml":
135 return OUTPUT_YAML
136 }
137}
138
139type CommandResult struct {
140 Format format.Format
141 Filter string
142 OrderBy string
143 OutputAs OutputType
144 NameLimit int
145 Data interface{}
146}
147
Zack Williamse940c7a2019-08-21 14:25:39 -0700148func ProcessGlobalOptions() {
149 if len(GlobalOptions.Config) == 0 {
150 home, err := os.UserHomeDir()
151 if err != nil {
152 log.Printf("Unable to discover they users home directory: %s\n", err)
153 home = "~"
154 }
155 GlobalOptions.Config = filepath.Join(home, ".volt", "config")
156 }
157
158 info, err := os.Stat(GlobalOptions.Config)
159 if err == nil && !info.IsDir() {
160 configFile, err := ioutil.ReadFile(GlobalOptions.Config)
161 if err != nil {
162 log.Printf("configFile.Get err #%v ", err)
163 }
164 err = yaml.Unmarshal(configFile, &GlobalConfig)
165 if err != nil {
166 log.Fatalf("Unmarshal: %v", err)
167 }
168 }
169
170 // Override from command line
171 if GlobalOptions.Server != "" {
172 GlobalConfig.Server = GlobalOptions.Server
173 }
174 if GlobalOptions.ApiVersion != "" {
175 GlobalConfig.ApiVersion = GlobalOptions.ApiVersion
176 }
177
178 // If a k8s cert/key were not specified, then attempt to read it from
179 // any $HOME/.kube/config if it exists
180 if len(GlobalOptions.K8sConfig) == 0 {
181 home, err := os.UserHomeDir()
182 if err != nil {
183 log.Printf("Unable to discover the user's home directory: %s\n", err)
184 home = "~"
185 }
186 GlobalOptions.K8sConfig = filepath.Join(home, ".kube", "config")
187 }
188}
189
190func NewConnection() (*grpc.ClientConn, error) {
191 ProcessGlobalOptions()
192 return grpc.Dial(GlobalConfig.Server, grpc.WithInsecure())
193}
194
195func GenerateOutput(result *CommandResult) {
196 if result != nil && result.Data != nil {
197 data := result.Data
198 if result.Filter != "" {
199 f, err := filter.Parse(result.Filter)
200 if err != nil {
201 panic(err)
202 }
203 data, err = f.Process(data)
204 if err != nil {
205 panic(err)
206 }
207 }
208 if result.OrderBy != "" {
209 s, err := order.Parse(result.OrderBy)
210 if err != nil {
211 panic(err)
212 }
213 data, err = s.Process(data)
214 if err != nil {
215 panic(err)
216 }
217 }
218 if result.OutputAs == OUTPUT_TABLE {
219 tableFormat := format.Format(result.Format)
David Bainbridge12f036f2019-10-15 22:09:04 +0000220 if err := tableFormat.Execute(os.Stdout, true, result.NameLimit, data); err != nil {
221 log.Fatalf("Unexpected error while attempting to format results as table : %s", err)
222 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700223 } else if result.OutputAs == OUTPUT_JSON {
224 asJson, err := json.Marshal(&data)
225 if err != nil {
226 panic(err)
227 }
228 fmt.Printf("%s", asJson)
229 } else if result.OutputAs == OUTPUT_YAML {
230 asYaml, err := yaml.Marshal(&data)
231 if err != nil {
232 panic(err)
233 }
234 fmt.Printf("%s", asYaml)
235 }
236 }
237}