gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/runsc/cmd/util/util.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package util groups a bunch of common helper functions used by commands. 16 package util 17 18 import ( 19 "encoding/json" 20 "fmt" 21 "io" 22 "os" 23 "time" 24 25 "github.com/google/subcommands" 26 "gvisor.dev/gvisor/pkg/log" 27 ) 28 29 // ErrorLogger is where error messages should be written to. These messages are 30 // consumed by containerd and show up to users of command line tools, 31 // like docker/kubectl. 32 var ErrorLogger io.Writer 33 34 type jsonError struct { 35 Msg string `json:"msg"` 36 Level string `json:"level"` 37 Time time.Time `json:"time"` 38 } 39 40 // Writer writes to log and stdout. 41 type Writer struct{} 42 43 // Write implements io.Writer. 44 func (i *Writer) Write(data []byte) (n int, err error) { 45 log.Infof("%s", data) 46 return os.Stdout.Write(data) 47 } 48 49 // Infof writes message to log and stdout. 50 func Infof(format string, args ...any) { 51 log.Infof(format, args...) 52 fmt.Printf(format+"\n", args...) 53 } 54 55 // Errorf logs error to containerd log (--log), to stderr, and debug logs. It 56 // returns subcommands.ExitFailure for convenience with subcommand.Execute() 57 // methods: 58 // 59 // return Errorf("Danger! Danger!") 60 func Errorf(format string, args ...any) subcommands.ExitStatus { 61 // If runsc is being invoked by docker or cri-o, then we might not have 62 // access to stderr, so we log a serious-looking warning in addition to 63 // writing to stderr. 64 log.Warningf("FATAL ERROR: "+format, args...) 65 fmt.Fprintf(os.Stderr, format+"\n", args...) 66 67 j := jsonError{ 68 Msg: fmt.Sprintf(format, args...), 69 Level: "error", 70 Time: time.Now(), 71 } 72 b, err := json.Marshal(j) 73 if err != nil { 74 panic(err) 75 } 76 if ErrorLogger != nil { 77 _, _ = ErrorLogger.Write(b) 78 } 79 80 return subcommands.ExitFailure 81 } 82 83 // Fatalf logs the same way as Errorf() does, plus *exits* the process. 84 func Fatalf(format string, args ...any) { 85 Errorf(format, args...) 86 // Return an error that is unlikely to be used by the application. 87 os.Exit(128) 88 }