blob: 12b869f638af8091913adbcc4c73d319913241e9 [file] [log] [blame]
Scott Baker2c0ebda2019-05-06 16:55:47 -07001/*
2 * Copyright 2019-present Open Networking Foundation
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 (
Scott Baker5281d002019-05-16 10:45:26 -070019 "bufio"
Scott Baker2c0ebda2019-05-06 16:55:47 -070020 b64 "encoding/base64"
Scott Baker6cf525a2019-05-09 12:25:08 -070021 "fmt"
22 "github.com/fullstorydev/grpcurl"
Scott Baker867aa302019-06-19 13:18:45 -070023 versionUtils "github.com/hashicorp/go-version"
24 "github.com/jhump/protoreflect/dynamic"
Scott Baker6cf525a2019-05-09 12:25:08 -070025 "github.com/jhump/protoreflect/grpcreflect"
Scott Baker20481aa2019-06-20 11:00:54 -070026 corderrors "github.com/opencord/cordctl/error"
Scott Baker6cf525a2019-05-09 12:25:08 -070027 "golang.org/x/net/context"
28 "google.golang.org/grpc"
29 reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
Scott Baker175cb402019-05-17 16:13:06 -070030 "google.golang.org/grpc/status"
Scott Baker5281d002019-05-16 10:45:26 -070031 "log"
32 "os"
33 "strings"
Scott Baker2c0ebda2019-05-06 16:55:47 -070034)
35
Scott Baker867aa302019-06-19 13:18:45 -070036// Flags for calling the InitReflectionClient Method
37const (
38 INIT_DEFAULT = 0
39 INIT_NO_VERSION_CHECK = 1 // Do not check whether server is allowed version
40)
41
Scott Baker2c0ebda2019-05-06 16:55:47 -070042func GenerateHeaders() []string {
43 username := GlobalConfig.Username
44 password := GlobalConfig.Password
45 sEnc := b64.StdEncoding.EncodeToString([]byte(username + ":" + password))
46 headers := []string{"authorization: basic " + sEnc}
47 return headers
48}
Scott Baker6cf525a2019-05-09 12:25:08 -070049
Scott Baker867aa302019-06-19 13:18:45 -070050// Perform the GetVersion API call on the core to get the version
51func GetVersion(conn *grpc.ClientConn, descriptor grpcurl.DescriptorSource) (*dynamic.Message, error) {
52 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
53 defer cancel()
54
55 headers := GenerateHeaders()
56
57 h := &RpcEventHandler{}
58 err := grpcurl.InvokeRPC(ctx, descriptor, conn, "xos.utility.GetVersion", headers, h, h.GetParams)
59 if err != nil {
60 return nil, err
61 }
62
63 if h.Status != nil && h.Status.Err() != nil {
64 return nil, h.Status.Err()
65 }
66
67 d, err := dynamic.AsDynamicMessage(h.Response)
68
69 return d, err
70}
71
72// Initialize client connection
73// flags is a set of optional flags that may influence how the connection is setup
74// INIT_DEFAULT - default behavior (0)
75// INIT_NO_VERSION_CHECK - do not perform core version check
76
77func InitClient(flags uint32) (*grpc.ClientConn, grpcurl.DescriptorSource, error) {
Scott Baker6cf525a2019-05-09 12:25:08 -070078 conn, err := NewConnection()
79 if err != nil {
80 return nil, nil, err
81 }
82
83 refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(conn))
84 defer refClient.Reset()
85
Scott Baker14c8f182019-05-22 18:05:29 -070086 // Intended method of use is to download the protos via reflection API. Loading the
87 // protos from a file is supported for unit testing, as the mock server does not
88 // support the reflection API.
89
90 var descriptor grpcurl.DescriptorSource
91 if GlobalConfig.Protoset != "" {
92 descriptor, err = grpcurl.DescriptorSourceFromProtoSets(GlobalConfig.Protoset)
93 if err != nil {
94 return nil, nil, err
95 }
96 } else {
97 descriptor = grpcurl.DescriptorSourceFromServer(context.Background(), refClient)
98 }
Scott Baker6cf525a2019-05-09 12:25:08 -070099
Scott Baker867aa302019-06-19 13:18:45 -0700100 if flags&INIT_NO_VERSION_CHECK == 0 {
101 d, err := GetVersion(conn, descriptor)
102 if err != nil {
103 return nil, nil, err
104 }
105 // Note: NewVersion doesn't like the `-dev` suffix, so strip it off.
106 serverVersion, err := versionUtils.NewVersion(strings.Split(d.GetFieldByName("version").(string), "-")[0])
107 if err != nil {
108 return nil, nil, err
109 }
110
111 constraint, err := versionUtils.NewConstraint(CORE_VERSION_CONSTRAINT)
112 if err != nil {
113 return nil, nil, err
114 }
115
116 if !constraint.Check(serverVersion) {
Scott Baker20481aa2019-06-20 11:00:54 -0700117 return nil, nil, corderrors.WithStackTrace(&corderrors.VersionConstraintError{
118 Name: "xos-core",
119 Version: serverVersion.String(),
120 Constraint: CORE_VERSION_CONSTRAINT})
Scott Baker867aa302019-06-19 13:18:45 -0700121 }
122
123 }
124
Scott Baker6cf525a2019-05-09 12:25:08 -0700125 return conn, descriptor, nil
126}
127
128// A makeshift substitute for C's Ternary operator
129func Ternary_uint32(condition bool, value_true uint32, value_false uint32) uint32 {
130 if condition {
131 return value_true
132 } else {
133 return value_false
134 }
135}
136
137// call printf only if visible is True
138func conditional_printf(visible bool, format string, args ...interface{}) {
139 if visible {
140 fmt.Printf(format, args...)
141 }
142}
Scott Baker5281d002019-05-16 10:45:26 -0700143
144// Print a confirmation prompt and get a response from the user
145func Confirmf(format string, args ...interface{}) bool {
146 if GlobalOptions.Yes {
147 return true
148 }
149
150 reader := bufio.NewReader(os.Stdin)
151
152 for {
153 msg := fmt.Sprintf(format, args...)
154 fmt.Print(msg)
155
156 response, err := reader.ReadString('\n')
157 if err != nil {
158 log.Fatal(err)
159 }
160
161 response = strings.ToLower(strings.TrimSpace(response))
162
163 if response == "y" || response == "yes" {
164 return true
165 } else if response == "n" || response == "no" {
166 return false
167 }
168 }
169}
Scott Baker175cb402019-05-17 16:13:06 -0700170
171func HumanReadableError(err error) string {
172 st, ok := status.FromError(err)
173 if ok {
174 grpc_message := st.Message()
175 if strings.HasPrefix(grpc_message, "Exception calling application: ") {
176 return st.Message()[31:]
177 } else {
178 return st.Message()
179 }
180 }
181 return err.Error()
182}