blob: c79c3ca2ccbe6a09697a89e4ead9ebfa3dcf454d [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 Baker5281d002019-05-16 10:45:26 -070030 "log"
31 "os"
32 "strings"
Scott Baker2c0ebda2019-05-06 16:55:47 -070033)
34
Scott Baker867aa302019-06-19 13:18:45 -070035// Flags for calling the InitReflectionClient Method
36const (
37 INIT_DEFAULT = 0
38 INIT_NO_VERSION_CHECK = 1 // Do not check whether server is allowed version
39)
40
Scott Baker2c0ebda2019-05-06 16:55:47 -070041func GenerateHeaders() []string {
42 username := GlobalConfig.Username
43 password := GlobalConfig.Password
44 sEnc := b64.StdEncoding.EncodeToString([]byte(username + ":" + password))
45 headers := []string{"authorization: basic " + sEnc}
46 return headers
47}
Scott Baker6cf525a2019-05-09 12:25:08 -070048
Scott Baker867aa302019-06-19 13:18:45 -070049// Perform the GetVersion API call on the core to get the version
50func GetVersion(conn *grpc.ClientConn, descriptor grpcurl.DescriptorSource) (*dynamic.Message, error) {
51 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
52 defer cancel()
53
54 headers := GenerateHeaders()
55
56 h := &RpcEventHandler{}
57 err := grpcurl.InvokeRPC(ctx, descriptor, conn, "xos.utility.GetVersion", headers, h, h.GetParams)
58 if err != nil {
Scott Bakera55e6452019-06-25 11:10:30 -070059 return nil, corderrors.RpcErrorToCordError(err)
Scott Baker867aa302019-06-19 13:18:45 -070060 }
61
62 if h.Status != nil && h.Status.Err() != nil {
Scott Bakera55e6452019-06-25 11:10:30 -070063 return nil, corderrors.RpcErrorToCordError(h.Status.Err())
Scott Baker867aa302019-06-19 13:18:45 -070064 }
65
66 d, err := dynamic.AsDynamicMessage(h.Response)
67
68 return d, err
69}
70
71// Initialize client connection
72// flags is a set of optional flags that may influence how the connection is setup
73// INIT_DEFAULT - default behavior (0)
74// INIT_NO_VERSION_CHECK - do not perform core version check
75
76func InitClient(flags uint32) (*grpc.ClientConn, grpcurl.DescriptorSource, error) {
Scott Baker6cf525a2019-05-09 12:25:08 -070077 conn, err := NewConnection()
78 if err != nil {
79 return nil, nil, err
80 }
81
82 refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(conn))
83 defer refClient.Reset()
84
Scott Baker14c8f182019-05-22 18:05:29 -070085 // Intended method of use is to download the protos via reflection API. Loading the
86 // protos from a file is supported for unit testing, as the mock server does not
87 // support the reflection API.
88
89 var descriptor grpcurl.DescriptorSource
90 if GlobalConfig.Protoset != "" {
91 descriptor, err = grpcurl.DescriptorSourceFromProtoSets(GlobalConfig.Protoset)
92 if err != nil {
93 return nil, nil, err
94 }
95 } else {
96 descriptor = grpcurl.DescriptorSourceFromServer(context.Background(), refClient)
97 }
Scott Baker6cf525a2019-05-09 12:25:08 -070098
Scott Baker867aa302019-06-19 13:18:45 -070099 if flags&INIT_NO_VERSION_CHECK == 0 {
100 d, err := GetVersion(conn, descriptor)
101 if err != nil {
102 return nil, nil, err
103 }
104 // Note: NewVersion doesn't like the `-dev` suffix, so strip it off.
105 serverVersion, err := versionUtils.NewVersion(strings.Split(d.GetFieldByName("version").(string), "-")[0])
106 if err != nil {
107 return nil, nil, err
108 }
109
110 constraint, err := versionUtils.NewConstraint(CORE_VERSION_CONSTRAINT)
111 if err != nil {
112 return nil, nil, err
113 }
114
115 if !constraint.Check(serverVersion) {
Scott Baker20481aa2019-06-20 11:00:54 -0700116 return nil, nil, corderrors.WithStackTrace(&corderrors.VersionConstraintError{
117 Name: "xos-core",
118 Version: serverVersion.String(),
119 Constraint: CORE_VERSION_CONSTRAINT})
Scott Baker867aa302019-06-19 13:18:45 -0700120 }
121
122 }
123
Scott Baker6cf525a2019-05-09 12:25:08 -0700124 return conn, descriptor, nil
125}
126
127// A makeshift substitute for C's Ternary operator
128func Ternary_uint32(condition bool, value_true uint32, value_false uint32) uint32 {
129 if condition {
130 return value_true
131 } else {
132 return value_false
133 }
134}
135
136// call printf only if visible is True
137func conditional_printf(visible bool, format string, args ...interface{}) {
138 if visible {
139 fmt.Printf(format, args...)
140 }
141}
Scott Baker5281d002019-05-16 10:45:26 -0700142
143// Print a confirmation prompt and get a response from the user
144func Confirmf(format string, args ...interface{}) bool {
145 if GlobalOptions.Yes {
146 return true
147 }
148
149 reader := bufio.NewReader(os.Stdin)
150
151 for {
152 msg := fmt.Sprintf(format, args...)
153 fmt.Print(msg)
154
155 response, err := reader.ReadString('\n')
156 if err != nil {
157 log.Fatal(err)
158 }
159
160 response = strings.ToLower(strings.TrimSpace(response))
161
162 if response == "y" || response == "yes" {
163 return true
164 } else if response == "n" || response == "no" {
165 return false
166 }
167 }
168}