github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/internal/googlecloud/googlecloud.go (about) 1 /* 2 * 3 * Copyright 2021 gRPC authors. 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 * 17 */ 18 19 // Package googlecloud contains internal helpful functions for google cloud. 20 package googlecloud 21 22 import ( 23 "errors" 24 "fmt" 25 "io" 26 "io/ioutil" 27 "os" 28 "os/exec" 29 "regexp" 30 "runtime" 31 "strings" 32 "sync" 33 34 "github.com/hxx258456/ccgo/grpc/grpclog" 35 internalgrpclog "github.com/hxx258456/ccgo/grpc/internal/grpclog" 36 ) 37 38 const ( 39 linuxProductNameFile = "/sys/class/dmi/id/product_name" 40 windowsCheckCommand = "powershell.exe" 41 windowsCheckCommandArgs = "Get-WmiObject -Class Win32_BIOS" 42 powershellOutputFilter = "Manufacturer" 43 windowsManufacturerRegex = ":(.*)" 44 45 logPrefix = "[googlecloud]" 46 ) 47 48 var ( 49 // The following two variables will be reassigned in tests. 50 runningOS = runtime.GOOS 51 manufacturerReader = func() (io.Reader, error) { 52 switch runningOS { 53 case "linux": 54 return os.Open(linuxProductNameFile) 55 case "windows": 56 cmd := exec.Command(windowsCheckCommand, windowsCheckCommandArgs) 57 out, err := cmd.Output() 58 if err != nil { 59 return nil, err 60 } 61 for _, line := range strings.Split(strings.TrimSuffix(string(out), "\n"), "\n") { 62 if strings.HasPrefix(line, powershellOutputFilter) { 63 re := regexp.MustCompile(windowsManufacturerRegex) 64 name := re.FindString(line) 65 name = strings.TrimLeft(name, ":") 66 return strings.NewReader(name), nil 67 } 68 } 69 return nil, errors.New("cannot determine the machine's manufacturer") 70 default: 71 return nil, fmt.Errorf("%s is not supported", runningOS) 72 } 73 } 74 75 vmOnGCEOnce sync.Once 76 vmOnGCE bool 77 78 logger = internalgrpclog.NewPrefixLogger(grpclog.Component("googlecloud"), logPrefix) 79 ) 80 81 // OnGCE returns whether the client is running on GCE. 82 // 83 // It provides similar functionality as metadata.OnGCE from the cloud library 84 // package. We keep this to avoid depending on the cloud library module. 85 func OnGCE() bool { 86 vmOnGCEOnce.Do(func() { 87 vmOnGCE = isRunningOnGCE() 88 }) 89 return vmOnGCE 90 } 91 92 // isRunningOnGCE checks whether the local system, without doing a network request is 93 // running on GCP. 94 func isRunningOnGCE() bool { 95 manufacturer, err := readManufacturer() 96 if err != nil { 97 logger.Infof("failed to read manufacturer %v, returning OnGCE=false", err) 98 return false 99 } 100 name := string(manufacturer) 101 switch runningOS { 102 case "linux": 103 name = strings.TrimSpace(name) 104 return name == "Google" || name == "Google Compute Engine" 105 case "windows": 106 name = strings.Replace(name, " ", "", -1) 107 name = strings.Replace(name, "\n", "", -1) 108 name = strings.Replace(name, "\r", "", -1) 109 return name == "Google" 110 default: 111 return false 112 } 113 } 114 115 func readManufacturer() ([]byte, error) { 116 reader, err := manufacturerReader() 117 if err != nil { 118 return nil, err 119 } 120 if reader == nil { 121 return nil, errors.New("got nil reader") 122 } 123 manufacturer, err := ioutil.ReadAll(reader) 124 if err != nil { 125 return nil, fmt.Errorf("failed reading %v: %v", linuxProductNameFile, err) 126 } 127 return manufacturer, nil 128 }